SpringMVC框架的文件上传和下载是基于commons-fileupload组件做了进一步封装的通用代码实现
1.导入commons-fileupload.jar包
首先需要maven导入commons-fileupload.jar(自动导入基础包commons-io.jar包)
<!-- 文件上传包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
2.在SpringMVC配置文件中实现相关配置
<!-- 文件上传解析器 -->
<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,不然会导致异常
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 {
// 为防止文件名重复,需要使用随机文件名+文件扩展名,但保存到数据库时应使用原文件名(不可用时间戳,因为在多线程的情况下有可能取到同一个时间戳)
// 不使用UUID,UUID入库性能并不好
String extName = file.getOriginalFilename();
int index = extName.lastIndexOf(".");
if(index > -1) {
extName = extName.substring(index);// 这里substring中参数不能为-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);// 将文件流转为字节数组
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);// 创建一个HTTPEntity实体,有响应头,响应体,状态码
return resp;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
}
}
UploadUtil的两个核心方法saveFile(MultipartFile file)
和downloadFile(String fileName)
分别实现上传和下载文件功能
- saveFile()
// 生成新的文件File类:"new File(服务器上保存文件的路径+生成的新随机文件名+文件后缀名(基于MultipartFile得到))"
// "file.transferTo(新File类)"表示以新文件类的方式保存到服务器路径上
// 返回新文件名
注意,为什么不用原文件名保存,因为原文件名很容易重名,只有用户要下载时才根据入库的新文件名返回原文件名,同时,使用UUID存文件名影响查询效率,推荐使用随机数或者雪花算法(snowflak)实现全局唯一文件名
- downloadFile()
// ResponseEntity<byte[]> resp = new ResponseEntity<byte[]>(body,headers,status);// 创建一个HTTPEntity实体并返回,有响应头headers,响应体body,状态码status,根据HTTPEntity实体决定返回的文件表现形式
4.在业务代码中实现相关功能
// 上传文件
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实现类,但是推荐使用MultipartFile
具体可看以下CommonsMultipartFile与MultipartFile的区别
https://blog.csdn.net/gao_zhe...
File转MultipartFile
File类转为MultipartFile
// File转为CommonsMultipartFile
FileItemFactory factory = new DiskFileItemFactory(16, null);
FileItem item = factory.createItem(shopImg.getName(), "text/plain", true, shopImg.getName());
MultipartFile multipartFile = new CommonsMultipartFile(item);
或者另外一种方式
MultipartFile file = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(originFile);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
try {
file = new MockMultipartFile(originFile.getName(), originFile.getName(),ContentType.IMAGE_PNG.toString(), fileInputStream);
} catch (IOException e1) {
e1.printStackTrace();
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。