gpt4 book ai didi

java - Servlet 输出流响应出现问题

转载 作者:行者123 更新时间:2023-12-01 15:44:53 25 4
gpt4 key购买 nike

在我的基于 Java 的 Web 应用程序中,我试图在 ZIP 文件中写入一些文件,并且我想提示用户下载/取消/保存。下载对话框打开时,如果我单击取消,之后如果我尝试访问应用程序中的任何链接,则该对话框将再次打开。这是我的代码片段。

private void sendResponse(byte[] buf, File tempFile) throws IOException {
long length = tempFile.length();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
String disposition = "attachment; fileName=search_download.zip";
ServletOutputStream servletOutputStream = null;
InputStream in = null;
try {
if (buf != null) {
in = new BufferedInputStream(new FileInputStream(tempFile));
servletOutputStream = response.getOutputStream();
response.setContentType("application/zip");
response.setHeader("Content-Disposition", disposition);
while ((in != null) && ((length = in.read(buf)) != -1)) {
servletOutputStream.write(buf, 0, (int) length);
}
}
} finally {
if (servletOutputStream != null) {
servletOutputStream.close();
}
if (in != null) {
in.close();
}
if (tempFile != null) {
tempFile.delete();
}
}
context.responseComplete();
}

此外,一旦我单击“保存/打开”,它就会按预期工作。我希望问题出在清除响应对象上。请帮我提供一些解决方案。

编辑下载选择方法

      public void downloadSelected() throws IOException {

List<NodeRef> list = init();
StringBuffer errors = new StringBuffer("");
ZipOutputStream out = null;

File tempFile = null;
byte[] buf = null;
try {
if (list != null && list.size() > 0) {
tempFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX_ZIP);
out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(tempFile)));
buf = writeIntoZip(list,out);
sendResponse(buf,tempFile);
} else {
errors.append("No Items Selected for Download");
this.errorMessage = errors.toString();
}
}
catch(IOException e) {
System.out.println("Cancelled");
}
}

写入Zip方法:

private byte[] writeIntoZip(List<NodeRef> list,ZipOutputStream out) throws IOException {
String downloadUrl = "";
InputStream bis = null;
Node node = null;
String nodeName = "";
byte[] buf = null;
Map<String,Integer> contents = new HashMap<String, Integer>();
ContentReader reader = null;
for (NodeRef nodeRef : list) {
try {
node = new Node(nodeRef);
nodeName = node.getName();
reader = Repository.getServiceRegistry(FacesContext.getCurrentInstance()).getContentService().getReader(nodeRef, ContentModel.PROP_CONTENT);
bis = new BufferedInputStream(reader.getContentInputStream());
if (bis != null) {
contents = setFiles(contents,nodeName);
nodeName = getUniqueFileName(contents, nodeName);
buf = new byte[4 * 1024];
buf = writeOutputStream(bis).toByteArray();
out.putNextEntry(new ZipEntry(nodeName));
out.write(buf);
}
} catch (Exception e) {
e.printStackTrace();
if(out != null) {
out.close();
}
}
}
if(out != null) {
out.close();
}
return buf;
}

谢谢,杰亚

最佳答案

我确实不确定这个问题的根本原因。根据迄今为止发布的代码,此行为无法解释。安SSCCE肯定会帮助更多。但我发现了这个问题的几个潜在原因。也许解决其中一个或全部问题就能解决具体问题。

  1. 您已分配 JSF 的 FacesContext作为 Bean 的属性。这是,而且如果它是一个范围比请求范围更广的bean,那么这肯定是不好的。它应该总是通过FacesContext#getCurrentInstance()在本地方法范围内获得。 。它返回一个线程局部变量,并且永远不应该在其他请求之间共享。也许您已将 bean 放入 session 范围并悬空 response将重用已设置 header 的上一个请求的对象。

  2. 您没有捕获 IOExceptionclose()方法。如果客户端取消下载,则servletOutputStream.close()会抛出 IOException表明客户端已中止响应。在您的情况下,in不会再被关闭,tempFile不会再被删除,并且 JSF 响应也不会再完成。您还应该捕获 close()并记录/忽略异常,以便您可以确保 finally完成它的工作。也许存在 tempFile会对您 future 的 POST 操作产生影响。

  3. 您正在使用<h:commandLink>而不是<h:outputLink><h:link>或普通<a>用于页面到页面的导航。这使用 POST 而不是 GET,这对于用户体验和 SEO 来说不好。您应该使用 GET 链接而不是 POST 链接。另请参阅When should I use h:outputLink instead of h:commandLink?

关于java - Servlet 输出流响应出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7260379/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com