|
SpringMVC框架的文件上傳和下載是基于commons-fileupload組件做了進一步封裝的通用代碼實現(xiàn)
1.導(dǎo)入commons-fileupload.jar包
首先需要maven導(dǎo)入commons-fileupload.jar(自動導(dǎo)入基礎(chǔ)包commons-io.jar包)
<!-- 文件上傳包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
2.在SpringMVC配置文件中實現(xiàn)相關(guān)配置
<!-- 文件上傳解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
p:defaultEncoding="UTF-8">
<property name="maxUploadSize" value="2097152" />
<property name="resolveLazily" value="true" />
</bean>
這里的文件解析器(multipartResolver)id必須是CommonsMultipartResolver的后單詞縮寫multipartResolver,不然會導(dǎo)致異常
3.編寫上傳和下載的工具類UploadUtil
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StreamUtils;
import org.springframework.web.multipart.MultipartFile;
public class UploadUtil {
public static String basePath = "D:\\Repositories\\uploadFiles\\";// 文件上傳保存路徑
/**
* 管理上傳文件的保存
* @param file
* @return 如果保存上傳文件成功,則返回新文件名,否則返回空""
*/
public static String saveFile(MultipartFile file) {
try {
// 為防止文件名重復(fù),需要使用隨機文件名+文件擴展名,但保存到數(shù)據(jù)庫時應(yīng)使用原文件名(不可用時間戳,因為在多線程的情況下有可能取到同一個時間戳)
// 不使用UUID,UUID入庫性能并不好
String extName = file.getOriginalFilename();
int index = extName.lastIndexOf(".");
if(index > -1) {
extName = extName.substring(index);// 這里substring中參數(shù)不能為-1否則報異常
} else {
extName = "";
}
// 隨機名+后綴命名并保存到basePath路徑下
String newFileName = Math.random() + extName;
File newFilePath = new File(basePath + newFileName);
while(newFilePath.exists()) {
newFileName = Math.random() + extName;
newFilePath = new File(basePath + newFileName);
}
file.transferTo(newFilePath);
return newFileName;
} catch (IllegalStateException | IOException e) {
e.printStackTrace();
}
return "";
}
public static ResponseEntity<byte[]> downloadFile(String fileName){
try(InputStream in = new FileInputStream(basePath+fileName)) {
byte[] body = StreamUtils.copyToByteArray(in);// 將文件流轉(zhuǎn)為字節(jié)數(shù)組
HttpHeaders headers = new HttpHeaders();
MediaType mediaType = MediaType.IMAGE_JPEG;
headers.setContentType(mediaType);
HttpStatus status = HttpStatus.OK;
ResponseEntity<byte[]> resp = new ResponseEntity<byte[]>(body,headers,status);// 創(chuàng)建一個HTTPEntity實體,有響應(yīng)頭,響應(yīng)體,狀態(tài)碼
return resp;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
}
}
UploadUtil的兩個核心方法saveFile(MultipartFile file)和downloadFile(String fileName)分別實現(xiàn)上傳和下載文件功能
// 生成新的文件File類:"new File(服務(wù)器上保存文件的路徑+生成的新隨機文件名+文件后綴名(基于MultipartFile得到))"
// "file.transferTo(新File類)"表示以新文件類的方式保存到服務(wù)器路徑上
// 返回新文件名
注意,為什么不用原文件名保存,因為原文件名很容易重名,只有用戶要下載時才根據(jù)入庫的新文件名返回原文件名,同時,使用UUID存文件名影響查詢效率,推薦使用隨機數(shù)或者雪花算法(snowflak)實現(xiàn)全局唯一文件名
// ResponseEntity<byte[]> resp = new ResponseEntity<byte[]>(body,headers,status);// 創(chuàng)建一個HTTPEntity實體并返回,有響應(yīng)頭headers,響應(yīng)體body,狀態(tài)碼status,根據(jù)HTTPEntity實體決定返回的文件表現(xiàn)形式
4.在業(yè)務(wù)代碼中實現(xiàn)相關(guān)功能
// 上傳文件
public String uploadFile(MultipartFile file) {
System.out.println("正在上傳文件");
String result = file.getOriginalFilename();
System.out.println("原始文件名:" + result);
result = UploadUtil.saveFile(file);
System.out.println("保存成功,新文件名:" + result);
return result;
}
// 下載文件
public ResponseEntity<byte[]> downloadFile(String fileName){
ResponseEntity<byte[]> resp = UploadUtil.downloadFile(fileName);
return resp;
}
說明:這里可以使用CommonsMultipartFile實現(xiàn)類,但是推薦使用MultipartFile 具體可看以下CommonsMultipartFile與MultipartFile的區(qū)別 https://blog.csdn.net/gao_zhe...
補充
File類轉(zhuǎn)為MultipartFile
// File轉(zhuǎn)為CommonsMultipartFile
FileItemFactory factory = new DiskFileItemFactory(16, null);
FileItem item = factory.createItem(shopImg.getName(), "text/plain", true, shopImg.getName());
MultipartFile multipartFile = new CommonsMultipartFile(item);
|