【问题标题】:Issues while File download文件下载时的问题
【发布时间】:2020-11-24 16:19:57
【问题描述】:

我正在尝试从 Angular UI 下载文件,即使在支持的代码中出现异常后,我仍然得到 200 ok 作为响应。

这是我的代码:

public ResponseEntity<Object> downloadDocument(@PathVariable("docId") Long docId,
            HttpServletResponse response) { 

OutPutStream outputStream = null;

try {
outputStream = response.getOutputStream();
docService.downloadDocument(docId,outputStream);
return ResponseEntity.ok().contentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
                    .body("Success");
} catch(Exception e) {
return ResponseEntity.badRequest().body(e.getMessage());
} finally {
if (Objects.nonNull(outputStream)) {
                IOUtils.closeQuietly(outputStream);
            }
}

请你帮我看看这里出了什么问题。

【问题讨论】:

  • 你去catch(Exception e) 吗?而你忘记了ResponseEntity.badRequest().body(e.getMessage());之前的返回
  • @Albanninou 抱歉编辑了问题

标签: java spring-boot download outputstream


【解决方案1】:

当您打开输出流时,会发送标头。期间。

从那时起就没有回溯了。你不能先打开输出流然后再去:哦,等等!不!没关系!错误的请求!

它的工作原理是这样的 - 你选择一方并坚持下去。您可以:

  1. 自己处理;使用response 和那里可用的方法来设置您的回复;您可以设置标头、返回码和消息,并且可以获得响应正文的输出流,并以这种方式发送数据。如果你这样做,你就不能ALSO返回一个 ResponseEntity!
  2. 甚至添加一个 HttpServletResponse 参数,而是返回一个 ResponseEntity 对象。

你两者都做,这是不允许的。

坦率地说,我很惊讶; spring 有点坏了,应该在这里抛出异常,因为它不可能满足你在这里要求它做的事情。

注意:请注意,异常的类型通常比消息更能提供信息(许多异常甚至没有消息)。

把它们放在一起:

public ResponseEntity<?> downloadDocument(@PathVariable("docId") Long docId) { 

  try {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    docService.downloadDocument(docId, baos);
    return ResponseEntity.ok()
      .contentType(MediaType.parseMediaType(MediaType.APPLICATION_OCTET_STREAM_VALUE))
      .body(baos.toByteArray());
  } catch(Exception e) {
    return ResponseEntity.badRequest().body(e.getMessage());
  }
}

'toString' 默认在没有消息时打印自己的类型,如果有则打印自己的类型加上消息,所以你得到例如:

NullPointerException

NullPointerException: parameter foo

这是你想要的(在前一种情况下是文字空白字符串,在后一种情况下只是'参数 foo',这也不是特别有洞察力)。

如果没有异常类型的上下文,消息通常不一定有意义。

注意:这会将下载文档的全部内容缓存到服务器的内存中,然后再发送。如果文档很大,这是个坏主意,但是,如果您想“流式传输”它,HTTP 协议固有的一个非常严重的问题:一旦开始发送,您就已经已经发送了“错误状态”(即您已经发送了 200 OK),因此如果文档下载过程中途抛出异常,您将无法返回并发送错误消息。您需要某种有线协议,您可以在其中分块发送正文并发送“类型”代码,以便接收者可以扫描这些并知道“这种类型意味着有更多数据流动”,并且“这种类型意味着发生错误,现在我可以阅读错误描述'。这一切都变得相当复杂。通过缓存它,您可以避免这种混乱。但是,如果该文档可能非常大,您将不得不处理上述问题,没有快速修复。

【讨论】:

  • 我正在尝试下载一个 50MB 的文件,正如你所说,如果我使用 ByteArrayOutputStream 我可能会出现内存错误,有没有更好的方法可以处理这个问题,抱歉第一次工作可能是个愚蠢的问题这么多文件下载
  • 必须设置有线协议或一些校验和系统。
  • 有没有参考我可以寻找这样的例子,非常适合你的帮助
猜你喜欢
  • 2019-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2018-02-10
  • 1970-01-01
  • 1970-01-01
  • 2019-03-16
相关资源
最近更新 更多