文件下载时出现问题
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。期间。
从那时起就没有回溯。你不能先打开输出流然后再去:哦,等等!不!没关系!请求错误!
这是它的工作原理 - 你选择一边并坚持下去。您可以:
- 自己处理;使用
response
和那里可用的方法来设置您的回复;您可以设置 headers、return 代码和消息,您可以获得响应 body 的输出流,并以这种方式发送数据。如果你这样做,你就不能 ALSO return ResponseEntity!
- 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'。这一切都变得相当复杂。通过缓存它,您可以避免这种混乱。但是,如果该文档可能非常大,您将不得不处理上述问题,没有快速修复方法。
我正在尝试从 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。期间。
从那时起就没有回溯。你不能先打开输出流然后再去:哦,等等!不!没关系!请求错误!
这是它的工作原理 - 你选择一边并坚持下去。您可以:
- 自己处理;使用
response
和那里可用的方法来设置您的回复;您可以设置 headers、return 代码和消息,您可以获得响应 body 的输出流,并以这种方式发送数据。如果你这样做,你就不能 ALSO return ResponseEntity! - 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'。这一切都变得相当复杂。通过缓存它,您可以避免这种混乱。但是,如果该文档可能非常大,您将不得不处理上述问题,没有快速修复方法。