springboot-springmvc文件上傳、下載、壓縮打包

前言

最近負責了一個需求:天天定時拉取第三方報表數據,生成文件,並能夠查看、下載、壓縮打包。java

遂單獨記錄下springmvc中文件的上傳、下載和壓縮打包這三個工做經常使用功能。spring

版本信息:api

<springcloud.version>Greenwich.SR2</springcloud.version>
<springboot.version>2.1.7.RELEASE</springboot.version>
(<spring.version>5.1.9.RELEASE</spring.version>)

文件上傳

  • 單文件上傳
//單文件上傳
@RequestMapping("/upload")
@ResponseBody
public BaseResult upload(@RequestParam("file") MultipartFile file) {
	//文件信息獲取
    String fileName = file.getOriginalFilename();
    long size = file.getSize()/1024; //單位 B>KB
    String contentType = file.getContentType();
    logger.info(">> file info to upload: {}, {}KB, {}", fileName, size, contentType);
    
    //目錄生成與新文件名
    String newFileName = currDateStr.substring(8, currDateStr.length()) + "_" + fileName;
    String dateDir = currDateStr.substring(0, 8); //20191220
    File destDir = new File(upload_fspath_base, dateDir);// /xxx/upload/20191220
    if(!destDir.exists()) {
    	destDir.mkdirs(); //注意不是mkdir
    }
    
	//文件寫入
	try {
		file.transferTo(new File(destDir, newFileName));
	} catch (IllegalStateException | IOException e) {
		logger.error("保存上傳文件出錯!", e);
		throw new BusinessException("保存上傳文件出錯!", e);
	}
	
	return BaseResult.succ();
}
  • 多文件上傳
//多文件上傳
@RequestMapping("/uploads")
@ResponseBody
public BaseResult uploads(@RequestParam("files") MultipartFile[] files) {
	int succSize = Arrays.stream(files).map(this::upload).collect(Collectors.toList()).size();
	
	return BaseResult.succData(succSize);
}
  • 注意:springboot預設的上傳大小限制爲10MB,對應配置項爲
spring.servlet.multipart.max-file-size=200MB
spring.servlet.multipart.max-request-size=200MB

文件下載

  • 方式1,使用 springmvc 的 ResponseEntity
//文件下載
@RequestMapping("/download/{code}")
public ResponseEntity<Resource> download(@PathVariable String code) { //上傳下載碼(惟一碼)
	//查找上傳記錄
	UploadFileInfo fileInfo = uploadFileInfoRepo.findByUploadCode(code);
	
	if(Objects.nonNull(fileInfo)) {
		Resource resource = null;
		String contentType = null;
		try {
			//load file as Resource 
			if(!RichardUtil.isStrEmpty(fileInfo.getFsPath())) {
				resource = new FileSystemResource(new File(fileInfo.getFsPath()));
			}else {
				resource = new UrlResource(fileInfo.getSrcPath());
			}
			contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
		} catch (IOException e) {
			logger.error(code, e);
			throw new BusinessException("資源讀取異常!", e);
		}
		if(Objects.isNull(contentType)) contentType = "application/octet-stream";
		
		return ResponseEntity.ok()
				.contentType(MediaType.parseMediaType(contentType))
				.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileInfo.getFileName() + "\"")
				.body(resource);
		
	}else {
		throw new BusinessException("資源未找到!");
	}
}
  • 方式2,傳統的 HttpServletResponse

見壓縮示例一塊兒springboot


文件壓縮/打包下載

  • 意外發現使用傳統的 response 更簡潔好用,使用 springmvc 的 ResponseEntity 的話修改返回類型便可
  • org.springframework.core.io.Resource 很好用
  • 代碼
/**
 * 文件(壓縮打包)下載,傳統response版
 */
@RequestMapping("/manage-api/download/zip5s")
@ResponseBody
public void zip5s() {
	List<UploadFileInfo> collect5 = uploadFileInfoRepo.findAll().stream().limit(5).collect(Collectors.toList());
	String showName = RichardUtil.getCurrentDatetimeStrNoFlag() + ".zip";
	//java7 資源自動關閉語法糖
	try(ZipOutputStream out = new ZipOutputStream(response.getOutputStream())){
		response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + showName + "\"");
		response.setContentType("application/octet-stream");
		for(UploadFileInfo o:collect5) {
			//load file resource
			Resource resource = RichardUtil.isStrEmpty(o.getFsPath())?new UrlResource(o.getSrcPath()):new FileSystemResource(o.getFsPath());
			//添加壓縮
			out.putNextEntry(new ZipEntry(o.getFileName()));
			//寫入(方法封裝,目的流暫不關閉)
			RichardUtil.dump_dest_not_close(resource.getInputStream(), out);
		}
	} catch (IOException e) {
		logger.error(">> zip壓縮打包異常", e);
		throw new BusinessException(e);
	}
}

文章原鏈,歡迎踩點

相關文章
相關標籤/搜索