2011年8月1日星期一

ADF_096:如何处理BLOB类型数据之二:下载BLOB内容并保存到文件中

实验环境:JDeveloper 11.1.2.0.0。
接上一个实验《如何处理BLOB类型数据之一:上传文件并保存到BLOB中》。

1. 修改页面代码,把Table中Filename字段改为CommandLink类型,这样点击文件名称即可下载该文件:
<af:commandLink text="#{row.Filename}" id="cl1" actionListener="#{myBackingBean.downloadLink_actionListener}"/>

2. 对应的Managed Bean代码
public void downloadLink_actionListener(ActionEvent actionEvent) {
FacesCtrlHierNodeBinding f = (FacesCtrlHierNodeBinding)this.richTable.getSelectedRowData();
Row row = f.getRow();
BlobDomain fileContent = (BlobDomain)row.getAttribute("Content");
String fileName = row.getAttribute("Filename").toString();
String fileType = "aplication/octet-stream";
if (fileName.endsWith(".pdf")) {
fileType = "application/PDF";
} else if (fileName.endsWith(".doc")) {
fileType = "aplication/msword";
} else if (fileName.endsWith(".txt")) {
fileType = "text/plain";
} else if (fileName.endsWith(".ppt")) {
fileType = "application/vnd.ms-powerpoint";
} else if (fileName.endsWith(".rar")) {
fileType = "aplication/octet-stream";
} else if (fileName.endsWith(".zip")) {
fileType = "aplication/zip";
} else if (fileName.endsWith(".jpg")) {
fileType = "aplication/jpg";
} else {
fileType = "aplication/octet-stream";
}
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext extContext = facesContext.getExternalContext();
Long length = fileContent.getLength();

HttpServletResponse response = (HttpServletResponse)extContext.getResponse();
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
response.setContentLength((int)length.intValue());

response.setBufferSize(1024);
response.setContentType(fileType);

try {
writeBlobDomainToOutputStream(fileContent,response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}

facesContext.responseComplete();
}

3. 运行,点击文件名,出现下载提示。


Project 下载:UploadFileToBlob_DownloadBlobToFile.7z

问题1:重复下载同一文件时,会报出异常:java.net.ProtocolException: Didn't meet stated Content-Length, wrote: '0' bytes instead of stated: '364' bytes。
经过跟踪调试,发现是while ((bytesRead = in.read(buffer, 0, 8192)) != -1) 循环并没有进入。
感觉像是inputStream没有关闭,读指针还停留在上一次结束的位置,即文件尾。
因此,再次读取同一文件时,in.read() == -1,直接返回了。
解决办法: 增加blobDomain.closeInputStream();。
由于BlobDomain对象比较特殊,in.close();并没有关闭BlobDomain对象输入流,必须使用BlobDomain自身的方法closeInputStream()来关闭。
Project已被更新,下载文件地址和名称不变。

没有评论: