1.整体思路
总体功能——通常做一个业务层面的"异步上传" : 即先让图片上传为临时文件(_TEMP后缀),返回文件地址对应图片地址表单value赋值,提交表单时,进行临时图片的"转正",不进行提交而存储的临时文件,设置定时任务对临时文件进行清理
2.功能实现
1>AppFileUtils
1 @PropertySource("classpath:file.properties") 2 public class AppFileUtils { 3 //文件上传的保存路径 4 @Value("${filepath}") 5 public static String UPLOAD_PATH="E:/upload/";//读取file.properties文件中定义的上传路径 6 7 /** 8 * 文件下载 9 * @param path 10 * @return 11 */ 12 public static ResponseEntity<Object> downloadFile(HttpServletResponse response, String path, String oldName) { 13 //1,构造文件对象 14 File file=new File(UPLOAD_PATH, path); 15 if(file.exists()) { 16 try { 17 //将下载的文件,封装byte[] 18 byte[] bytes=null; 19 try { 20 bytes = FileUtil.readBytes(file); 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } 24 25 //创建封装响应头信息的对象 26 HttpHeaders header=new HttpHeaders(); 27 //封装响应内容类型(APPLICATION_OCTET_STREAM 响应的内容不限定) 28 header.setContentType(MediaType.APPLICATION_OCTET_STREAM); 29 //设置下载的文件的名称 30 //header.setContentDispositionFormData("attachment", oldName); 31 //创建ResponseEntity对象 32 ResponseEntity<Object> entity= 33 new ResponseEntity<Object>(bytes, header, HttpStatus.CREATED); 34 return entity; 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 return null; 39 }else { 40 PrintWriter out; 41 try { 42 out = response.getWriter(); 43 out.write("文件不存在"); 44 out.flush(); 45 out.close(); 46 } catch (IOException e) { 47 e.printStackTrace(); 48 } 49 return null; 50 } 51 52 } 53 54 /** 55 * 根据相对路径删除硬盘上文件 56 * @param path 57 */ 58 public static void deleteFileUsePath(String path) { 59 String realPath=UPLOAD_PATH+path; 60 //根据文件 61 File file=new File(realPath); 62 if(file.exists()) { 63 file.delete(); 64 } 65 } 66 67 /** 68 * 删除文件临时后缀 69 * @param imgPath 带后缀的原文件全名 70 * @param suffix 要删除的文件后缀名 71 * @return 修改后名称 72 */ 73 public static String updateFileName(String imgPath,String suffix) { 74 //找到文件 75 try { 76 File file=new File(UPLOAD_PATH,imgPath); 77 if(file.exists()) { 78 file.renameTo(new File(UPLOAD_PATH,imgPath.replace(suffix, ""))); 79 return imgPath.replace(suffix, ""); 80 } 81 } catch (Exception e) { 82 e.printStackTrace(); 83 } 84 return null; 85 } 86 87 /** 88 * 根据路径 删除图片 89 * @param imgName 90 */ 91 public static void removeFileByPath(String imgName) { 92 try { 93 File file=new File(UPLOAD_PATH,imgName); 94 if(file.exists()) { 95 file.delete(); 96 } 97 } catch (Exception e) { 98 e.printStackTrace(); 99 } 100 }
2>FileController
1 @Controller 2 @RequestMapping("file") 3 public class FileController { 4 /** 5 * 上传文件,异步上传,首先保存为临时文件 6 * @throws IOException 7 * @throws IllegalStateException 8 */ 9 @RequestMapping("uploadFile") 10 @ResponseBody 11 public DataGridView uploadFile(MultipartFile mf) throws IllegalStateException, IOException { 12 // 文件上传的父目录 13 String parentPath = AppFileUtils.UPLOAD_PATH; 14 // 得到当前日期作为文件夹名称 15 String dirName = DateUtil.format(new Date(),"yyyy-MM-dd"); 16 // 构造文件夹对象 17 File dirFile = new File(parentPath, dirName); 18 if (!dirFile.exists()) { 19 dirFile.mkdirs();// 创建文件夹 20 } 21 // 得到文件原名 22 String oldName = mf.getOriginalFilename(); 23 // 根据文件原名得到有临时后缀名的新名-->此时使用旧文件名只是获取后缀名 24 String newName = RandomUtils.createFileNameUseTime(oldName, SysConstat.UPLOAD_FILE_TEMPSUFFIX); 25 File dest = new File(dirFile, newName); 26 mf.transferTo(dest); 27 28 Map<String,Object> map=new HashMap<>(); 29 //返回上传文件的路径,以供数据库中存储,以及页面的显示(页面显示-->下载方法) 30 map.put("src", dirName+"/"+newName); 31 return new DataGridView(map); 32 } 33 34 /** 35 * 下载图片 36 * @param path 37 * @param response 38 * @return 39 */ 40 @RequestMapping("downloadFile") 41 public ResponseEntity<Object> downloadFile(String path, HttpServletResponse response, HttpSession session) { 42 if(path==null||"".equals(path)){ 43 path = ((ActiveUser)session.getAttribute("user")).getUser().getImgpath(); 44 } 45 //不是真正意义的下载图片,只是显示图片 46 String oldName=""; 47 return AppFileUtils.downloadFile(response, path, oldName); 48 } 49 50 51 }
3>提交数据时临时文件的处理
- 上传 : 上传成功后返回上传文件地址,渲染图片时对应图片的下载方法传入返回的地址,地址表单赋值
done: function(res, index, upload){ //上传完成后显示图片-->下载显示图片 $('#userFace').attr('src','/file/downloadFile?path='+res.data.src); //给img的input框赋图片地址值 $('#imgpath').val(res.data.src); }
- 提交新增 : 判断是否是默认图片➡不是默认图片,则是临时图片➡临时图片后缀删除"转正"
@RequestMapping("addCar.do") public ResultObj addCar(CarVo carVo) { try { //临时图片转正后进行添加 //如果不是默认图片的话,才进行临时图片的转正 if(carVo.getCarimg().equals(SysConstast.DEFAULT_CAR_IMG)) { String fileName = AppFileUtils.updateFileName(carVo.getCarimg(), SysConstast.FILE_UPLOAD_TEMP); carVo.setCarimg(fileName); } carService.addCar(carVo); } catch (Exception e) { e.printStackTrace(); return ResultObj.ADD_ERROR; } return ResultObj.ADD_SUCCESS; }
- 提交修改 : 判断是否修改过➡没有修改一定经过转正,没有临时后缀➡修改过是临时图片➡临时图片后缀删除"转正"➡原有图片查询到对应文件删除
@RequestMapping("updateUserInfo") public ResultObj updateUserInfo(UserVo userVo, HttpSession session) { try { //判断图片后缀名是否是临时文件 String imgpath = userVo.getImgpath(); User user = ((ActiveUser) session.getAttribute("user")).getUser(); if (imgpath.endsWith(SysConstat.UPLOAD_FILE_TEMPSUFFIX)) { //是临时文件,改变文件为正式文件 imgpath = AppFileUtils.updateFileName(imgpath, SysConstat.UPLOAD_FILE_TEMPSUFFIX); //删除原有的头像 //查到原来地址,删除 String oldImgpath = user.getImgpath(); AppFileUtils.deleteFileUsePath(oldImgpath); } //将原本信息获取,并更新session中用户数据-->或者查询数据库 user.setName(userVo.getName()); user.setSex(userVo.getSex()); user.setRemark(userVo.getRemark()); user.setImgpath(imgpath); userService.updateById(user); } catch (Exception e) { e.printStackTrace(); return ResultObj.UPDATE_ERROR; } return ResultObj.UPDATE_SUCCESS; }
4>定时清理临时文件(处理上传不提交导致零食文件的产生问题)
@Component @EnableScheduling //开启定时任务 public class RecyleTempFileTask { /** * 每天晚上12点执行 */ @Scheduled(cron="0 0 0 * * ? ") public void recyleTempFile() { File file=new File(AppFileUtils.PATH); deleteFile(file); } /** * 删除图片 * @param file */ public void deleteFile(File file) { if(null!=file) { File[] listFiles = file.listFiles(); if(null!=listFiles&&listFiles.length>0) { for (File f : listFiles) { if(f.isFile()) { if(f.getName().endsWith(SysConstast.FILE_UPLOAD_TEMP)) { f.delete(); } }else { //如果是文件夹,再递归删除 deleteFile(f); } } } } } }