我正在使用servlet,用于开放文档,如doc,txt,pdf,ppt等。
我的代码段如下。
Documents document = db.getDocument(docCode);
String contentType = document.getDocMimeType();
byte[] docContentBytes = document.getDocContentBytes();
ServletOutputStream out = response.getOutputStream ();
response.setHeader("X-UA-Compatible", "IE=8");
response.setHeader("Content-disposition", "attachment;filename=\"Document\"");
response.setHeader("Pragma","private");
response.setHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-Transfer-Encoding","binary");
if(contentType!=null){
response.setContentType(contentType);
}else{
response.setContentType("application/pdf");
}
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
ByteArrayInputStream bais = null;
if(docContentBytes != null) {
try{
bais = new ByteArrayInputStream(docContentBytes);
bis = new BufferedInputStream(bais);
bos = new BufferedOutputStream(out);
byte[] buff = new byte[2048];
int bytesRead;
// Simple read/write loop.
while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
}catch(final MalformedURLException e) {
System.out.println ( "MalformedURLException." );
throw e;
} catch(final IOException e) {
System.out.println ( "IOException." );
throw e;
} finally {
if (bais != null)
bais.close();
if (bis != null)
bis.close();
if (bos != null)
bos.close();
}
}
现在,当我尝试打开多个文档时,经过一段时间后,我将从tomcat服务器中收到管道错误。
我的DataSource实现如下。
<Resource name="jdbc/TEST_DS"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://hostName;databaseName=TEST"
username="test"
password="testPwd"
maxPoolSize="50"
removeAbandoned="true"
removeAbandonedTimeout="1000"
logAbandoned="true"
/>
任何人都可以在此代码中建议我需要修改的内容吗?
答案 0 :(得分:1)
通过查看答案here,看起来关闭的顺序可能导致问题。
更改此代码......
finally {
if (bais != null)
bais.close();
if (bis != null)
bis.close();
if (bos != null)
bos.close();
}
要...
finally {
bais.close();
bos.close();
bis.close();
}
答案 1 :(得分:1)
获得该错误有几个原因:
您需要做的是按此顺序关闭:
finally {
if(bos != null)
bos.close();
if(bis != null)
bis.close();
if(bais != null)
bais.close();
}
希望这有帮助!
答案 2 :(得分:1)
您不应该关闭响应的输出流。我不确定这是否会导致管道损坏,但我肯定会试一试。
Documents document = db.getDocument(docCode);
String contentType = document.getDocMimeType();
byte[] docContentBytes = document.getDocContentBytes();
ServletOutputStream out = response.getOutputStream();
response.setHeader("X-UA-Compatible", "IE=8");
response.setHeader("Content-disposition", "attachment;filename=\"Document\"");
response.setHeader("Pragma", "private");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-Transfer-Encoding", "binary");
if (contentType != null) {
response.setContentType(contentType);
} else {
response.setContentType("application/pdf");
}
if (docContentBytes != null) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(docContentBytes);
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bais.read(buff))) {
out.write(buff, 0, bytesRead);
}
} finally {
out.flush();
}
}
以下是其他一些指示:
缓冲字节数组输入流没有意义;你已经有了内存中的数据
关闭缓冲流也会关闭基础流
关闭字节数组流不会做任何事情
缓冲响应的输出流没有意义,因为您已经使用了 代码中的缓冲机制
在处理流/文件时,例如common-io等第三方库非常有用(例如IOUtils)
您的异常堆栈跟踪的帖子(部分)发布了关于异常的问题
答案 3 :(得分:1)
你已经在byte [] docContentBytes内部加载了所有文件内容,那你为什么需要缓冲呢?
但是,如果异常是由tomcat和浏览器/客户端之间的通信错误引起的,请尝试删除缓冲并设置content-length。
否则,如果异常是由tomcat和SQL Server之间的通信错误引起的,那么你的问题就在于:
db
课程实施Documents
实施但是这就是我编写这个servlet的方式:
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException
{
Database db = Database.getInstance();
String docCode = request.getParameter("docCode");
if(docCode == null || docCode.isEmpty()) throw new IllegalArgumentException("docCode is null");
Documents document = db.getDocument(docCode);
if(document == null) throw new IllegalStateException("invalid docCode: " + docCode);
byte[] docContentBytes = document.getDocContentBytes();
if(docContentBytes == null) throw new IllegalStateException("document " + docCode + " has no content");
String contentType = document.getDocMimeType();
if(contentType == null) contentType = "application/octet-stream";
response.setHeader("X-UA-Compatible", "IE=8");
response.setHeader("Content-disposition", "attachment;filename=\"Document\"");
response.setHeader("Pragma", "private");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-Transfer-Encoding", "binary");
response.setContentType(contentType);
response.setContentLength(docContentBytes.length);
response.getOutputStream().write(docContentBytes);
}