SpringMVC框架的文件上传和下载是基于commons-fileupload组件做了进一步封装的通用代码实现
首先需要maven导入commons-fileupload.jar(自动导入基础包commons-io.jar包)
<!-- 文件上传包 --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.3</version> </dependency>
<!-- 文件上传解析器 --> <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,不然会导致异常
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)
分别实现上传和下载文件功能
// 生成新的文件File类:"new File(服务器上保存文件的路径+生成的新随机文件名+文件后缀名(基于MultipartFile得到))" // "file.transferTo(新File类)"表示以新文件类的方式保存到服务器路径上 // 返回新文件名
注意,为什么不用原文件名保存,因为原文件名很容易重名,只有用户要下载时才根据入库的新文件名返回原文件名,同时,使用UUID存文件名影响查询效率,推荐使用随机数或者雪花算法(snowflak)实现全局唯一文件名
// ResponseEntity<byte[]> resp = new ResponseEntity<byte[]>(body,headers,status);// 创建一个HTTPEntity实体并返回,有响应头headers,响应体body,状态码status,根据HTTPEntity实体决定返回的文件表现形式
// 上传文件 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; }