文件下载时出现问题

Issues while File download

我正在尝试从 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);
            }
}

你能帮我看看这是怎么回事吗?

当您打开输出流时,将发送 headers。期间。

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

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

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

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

坦率地说,我很惊讶; 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

这就是你想要的(相对于前一种情况下的文字空白字符串,后者只是 'parameter foo',这也不是特别有见地)。

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

注意:这会将下载文档的全部内容缓存到服务器的内存中,然后再发送。如果文档很大,这是个坏主意,但是,如果你想 'stream' 它,你有一个非常严重的 HTTP 协议固有的问题:一旦你开始发送时,你已经发送了'error status'(即你已经发送了200 OK),所以如果文档下载过程中途抛出异常,你将无法返回并发送错误信息。您需要某种有线协议,在其中以块的形式发送 body 并发送 'type' 代码,以便收件人可以扫描这些代码并知道“这种类型意味着有更多数据流”,和 'this type means an error occured and now I can read the error description'。这一切都变得相当复杂。通过缓存它,您可以避免这种混乱。但是,如果该文档可能非常大,您将不得不处理上述问题,没有快速修复方法。