解决Springboot文件下载接口无法下载文件和Cannot call sendError()和No converter for [XXX]

解决Springboot文件下载接口无法下载文件和 No converter for [XXX] with preset Content-Type 'application/octet-stream’和Cannot call sendError() after the response has been committed

首先看Controller里的方法,这里只复制了方法,没有把整个类复制下来,接口类有@RestController

@GetMapping("/temp/download")
public ResponseMessage managerDownload(HttpServletRequest request, HttpServletResponse response) {
   // 获取当前登陆用户对象
   User loginUser = (User) SecurityUtils.getSubject().getPrincipal();
   if (!loginUser.getUserType().equals(UserType.MANAGER.getType())) {
       return ResponseMessage.newErrorInstance("无法下载对应报告模版");
   }
   // 获取模版所属服务器路径
   ReportTemplate reportTemplate = reportService.getReportTemplateByMajor(loginUser.getUserBelong());
   String filePath;
   if (ObjectUtil.isNotNull(reportTemplate)) {
       filePath = reportTemplate.getPath();
   } else {
       return ResponseMessage.newErrorInstance("暂无报告模版");
   }
   // 截取文件名
   String fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
   FileInputStream fis = null;
   BufferedInputStream bis = null;
   try {
       response.setHeader("content-type", "application/octet-stream");
       response.setContentType("application/octet-stream");
       response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
       // 输入流
       bis = new BufferedInputStream(new FileInputStream(new File(filePath)));
       // 输出流
       OutputStream os = response.getOutputStream();
       byte[] buffer = new byte[1024];
       int temp = 0;
       // 每次读取的字符串长度
       while ((temp = bis.read(buffer)) != -1) {
           os.write(buffer, 0, temp);
       }
       return ResponseMessage.newSuccessInstance("下载模版成功");
   } catch (Exception e) {
       logger.error("用户{}下载模版失败: {}", loginUser.getRealName(), e.getMessage());
       return ResponseMessage.newErrorInstance("下载模版失败");
   } finally {
       if (ObjectUtil.isNotNull(bis)) {
           try {
               bis.close();
           } catch (IOException e) {
               logger.error("{}", e.getMessage());
           }
       }
       if (ObjectUtil.isNotNull(fis)) {
           try {
               fis.close();
           } catch (IOException e) {
               logger.error("{}", e.getMessage());
           }
       }
   }
}

返回的ResponseMessage是一个自定义的统一返回数据的包装类

重点在try catch语句块内:

 try {
       response.setHeader("content-type", "application/octet-stream");
       response.setContentType("application/octet-stream");
       response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
       // 输入流
       bis = new BufferedInputStream(new FileInputStream(new File(filePath)));
       // 输出流
       OutputStream os = response.getOutputStream();
       byte[] buffer = new byte[1024];
       int temp = 0;
       // 每次读取的字符串长度
       while ((temp = bis.read(buffer)) != -1) {
           os.write(buffer, 0, temp);
       }
       return ResponseMessage.newSuccessInstance("下载模版成功");
   } catch (Exception e) {
   		//就不全部复制了
	}

首先第一个点:文件没法下载的问题

创建输入流的时候用的是

bis = new BufferedInputStream(new FileInputStream(new File(filePath)));

但其实new File(filePath)是冗余的,所以删掉,直接改成:

bis = new BufferedInputStream(new FileInputStream(filePath));

这样能解决文件没法下载的问题

接着是No converter for [XXX] with preset Content-Type ‘application/octet-stream’ 和 Cannot call sendError() after the response has been committed问题

解决方案是:将方法的返回值改为void,并将所有return对象改为return;

@GetMapping("/temp/download")
public void managerDownload(HttpServletRequest request, HttpServletResponse response) {
	.......
}

这样就能正常的下载文件而且不会疯狂报错了。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值