我用oracle的BLOB存储附件文件,并保存了附件名称。我用一个servlet和一个jsp联合起来来处理附件文件的下载,servlet负责将附件文件从数据库中去出来存储到本地文件系统,jsp负责将文件从本地文件系统下载到浏览器。
期间我尝试了网上能够找到的多种方法,问题主要集中在下载那里.下面我列举一下我所遇到的下载问题:
- 能够下载执行下载以后的第一个附件下载,后边无法正确下载,只能下载到空文件或者只有一行文本。
- 能够正确下载,但是在文件首行添加了额外的一行。
- 只能下载到空文件。
我采用的方法:
- 采用从response中获得流直接输出。
ServletOutputStream sos = response.getOutputStream();
InputStream pi = resultset.getBinaryStream("DATABLOB");//字段名datablob
byte[] blobbytes = new byte[0x100000]; //照片大小
int bytesRead = 0;
while ((bytesRead = pi.read(blobbytes)) != -1) {
sos.write(blobbytes, 0, bytesRead);
//System.out.println(""+ (bytecount++));
}
pi.close();
sos.flush();
- 采用本地文件流
response.setContentType("application/octet-stream; charset=iso-8859-1");
response.setHeader("Content-disposition", "attachment; filename=\"" + dst_fname + "\"");
FileInputStream fis = null;
int byteRead;
out.clear();
try{
fis=new FileInputStream(filepath);
while ((byteRead = fis.read()) != -1) {
out.write(byteRead);
}
out.flush();
- 采用网络URL流
String src_fname = "http://www.javaworld.com.tw/jute/images_zh_TW/bluetitle.gif";
String dst_fname = URLEncoder.encode("bluetitle.gif", "Big5");
response.setContentType("application/octet-stream; charset=iso-8859-1");
response.setHeader("Content-disposition", "attachment; filename=\"" + dst_fname + "\"");
URL url = new URL(src_fname);
InputStream is = url.openStream();
DataInputStream fis = null;
int byteRead;
try{
fis = new DataInputStream(is);
while ((byteRead = fis.read()) != -1) {
out.write(byteRead);
}
out.flush();
}catch(Exception e){
out.clearBuffer();
response.setContentType("text/html; charset=big5");
response.setHeader("Content-disposition", "inline");
out.println("<HTML><BODY><P>");
out.println(e.toString());
out.println("</P></BODY></HTML>");
}
if(fis != null){
fis.close();
}
return;
我的具体代码如下:
import org.apache.log4j.Logger;
import java.io.*;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 把指定完整路径的文件存到tzfb的fj字段,时间关系没有设计成可重用类,只能为该表服务
*
* @author yyh 16:31:26
*
* FileImport
*/
public class FileImport {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(FileImport.class);
private Connection conn;
private Statement querryStm;
private Statement updateStm;
private String theLocalFile;
private String tzid=null;
private String dwdm=null;
public FileImport() throws SQLException
{
getConnection();
}
private int getConnection(){
//获取数据库连接
IDBOperate idbo=new IDBOperate();
DBOperate dbo=idbo.getDBOperate();
this.conn = dbo.getConnection();
try{
this.conn.setAutoCommit(false);
}catch(Exception e){
logger.warn(dwdm+"-无法连接数据库服务器,附件文件导入失败!");
e.printStackTrace();
}
if(conn==null){
return -1;
}
return 0;
}
/**
* 把指定完整路径的文件存到tzfb的fj字段,时间关系没有设计成可重用类,只能为该表服务
*
* Method 'importFile'
* @param theLocalFolder
* @param tzid
* @param dwdm
* @return
* 0:正常导入
* -1:附件文件导入数据库异常
* -2:附件文件导入数据库时IO异常
* -3:给定id的通知并不存在
* -4:给定附件文件路径不是一个文件
* -5:无法获得数据库连接
* -6:文件导入时无法建立Statement
*/
public int importFile(String theLocalFile,String tzid,String dwdm){
//init
this.theLocalFile = theLocalFile;
this.tzid=tzid;
this.dwdm=dwdm;
if(null==conn){
if(0!=getConnection())
return -5;
}
int result=0;
try{
this.querryStm = this.conn.createStatement();
this.updateStm = this.conn.createStatement();
}catch(Exception e){
logger.warn(dwdm+"-文件导入时无法建立Statement,附件文件导入失败");
e.printStackTrace();
return -6;
}
result=doImport( this.theLocalFile);
if (this.conn != null){
try{
this.querryStm.close();
this.updateStm.close();
this.conn.close();
}catch(Exception e){
System.out.println("数据库连接释放失败");
e.printStackTrace();
}
}
return result;//正常导入
}
/**
* 根据文件路径将文件导入到前边指定tzid的通知数据FJ中
*
* Method 'goThroughFileTree'
* @param FolderName
* @return
* 0:正常导入
* -1:附件文件导入数据库异常
* -2:附件文件导入数据库时IO异常
* -3:给定id的通知并不存在
* -4:给定附件文件路径不是一个文件
*/
private int doImport(String FolderName)//遍历整个文件树
{
int result=0;
File currentFile = new File(FolderName);
if(currentFile.isFile())
{
try
{
result=doImport(currentFile);
}
catch (SQLException e)
{
logger.warn(dwdm+"附件文件导入数据库异常,附件文件导入失败");
e.printStackTrace();
return -1;
}
catch (IOException e)
{
logger.warn(dwdm+"-附件文件导入数据库时IO异常,附件文件导入失败");
e.printStackTrace();
return -2;
}
}else{
logger.warn(dwdm+"-给定附件文件路径不是一个文件,附件文件导入失败");
return -4;
}
if(-1==result){
return -3;
}
//如果上述错误都没有发生就返回正确值0
return 0;
}
/**
* 将附件文件装载进数据库文件
*
* Method 'doImport'
* @param file
* @return
* 0:文件正常导入数据库
* -1:给定id的通知并不存在
* @throws SQLException
* @throws IOException
*/
private int doImport(File file) throws SQLException, IOException
{
String queryString;
System.out.println("路径---"+file.getPath() + " 文件名---"+file.getName());
FileInputStream fileIn = new FileInputStream(file);
queryString ="SELECT DLID FROM tzFB WHERE id ="+tzid;
System.out.println(queryString);
ResultSet theRS = this.querryStm.executeQuery(queryString);
if(theRS.next())//假设该id的通知一定存在
{
queryString ="SELECT FJ FROM TZFB WHERE id ="+tzid+" FOR UPDATE";
theRS = this.querryStm.executeQuery(queryString);
System.out.println(queryString);
if(theRS.next())
{
oracle.sql.BLOB blob = (oracle.sql.BLOB)theRS.getBlob("FJ");
BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());
BufferedInputStream in = new BufferedInputStream(fileIn);
int c;
while ((c=in.read())!=-1)
{
out.write(c);
}
in.close();
out.close();
this.conn.commit();
}
return 0;
}
else{//如果没有这个id的通知,那么则报告错误
logger.warn(dwdm+"-通知id错误,数据库中没有该id的通知,附件文件导入失败");
return -1;
}
}
public static void main(String arg[])
{
try
{
FileImport thePI = new FileImport();
thePI.importFile("C:\\tomcat5.5.8\\webapps\\gsmis\\main_images\\button\\000000000.JPG","12","1101'");
}
catch (SQLException e)
{
System.out.print("导入文件发生错误");
e.printStackTrace();
}
}
}
public class ExportAttachmentFile extends LEV1Servlet {
/**
* Logger for this class
*/
private static final Logger logger = Logger.getLogger(ExportAttachmentFile.class);
private String id=null;
/**
* 1.查找当前用户是否是指定id的通知接受者或者发出者,如果不是返回到错误页面
* 2.下载附件文件
*/
public void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String cxp=req.getContextPath();
HttpSession session=req.getSession(true);
String dwdm=(String)session.getAttribute("userID");
String fileSeparator = System.getProperty("file.separator");
ServletContext context=session.getServletContext();
String dbpath=context.getInitParameter("systemPath");
String userPath=dbpath+fileSeparator+dwdm; //like '/opt/tomcat/webapps/wb/db/1101'
// String host = "http://" + req.getServerName() + ":" + req.getServerPort() + "/" + req.getContextPath();
String host = "http://" + req.getServerName() + ":" + req.getServerPort() + req.getContextPath();
String download_url = host+"/db/"+dwdm+"/";
//验证dwdm
if(null==dwdm){
logger.warn("xxxxx-未登录时试图下载下载通知附件文件,ip:"+req.getRemoteAddr());
req.setAttribute("message", "无权下载通知附件文件,请登录系统!");
forward(req, res, "/pub/failure.jsp");
return;
}
//验证tzid
id=req.getParameter("tzid");
if(null==id){
logger.warn(dwdm+"-下载在附件时未指定通知id!");
req.setAttribute("nextPage", cxp+"/index.jsp");
req.setAttribute("message", "下载错误,请重试或联系客服人员!");
forward(req, res, "/pub/failure.jsp");
return;
}
//验证用户是否可以下载
String sql_tzfb="select dlid from tzfb where id="+id;
String sql_tzfbdx="select count(*) from tzfbdx where tzid="+id+" and dwid='"+dwdm+"'";
IDBOperate idbo=new IDBOperate();
DBOperate dbo=idbo.getDBOperate();
int count=dbo.queryTotalRowCount(sql_tzfbdx);
if(0==count){//如果不是通知的接受对象
ResultSet rs=null;
try{
rs=dbo.getResultSet(sql_tzfb);
if(rs.next()){//如果存在该id的通知
String dlid=rs.getString("dlid");
if(!dlid.equals(dwdm)){//如果还不是通知的发布对象
logger.warn(dwdm+"-无权下载该通知附件!tzid="+id);
req.setAttribute("nextPage", cxp+"/form/index.jsp");
req.setAttribute("message", "无权下载该通知附件,下载错误,请重试或联系客服人员!");
forward(req, res, "/pub/failure.jsp");
return;
}
}else{//如果不存在该id的通知
logger.warn(dwdm+"-不存在id="+id+"的通知!");
req.setAttribute("nextPage", cxp+"/form/index.jsp");
req.setAttribute("message", "不存在的通知,下载错误,请重试或联系客服人员!");
forward(req, res, "/pub/failure.jsp");
return;
}
}catch(Exception e){
logger.warn(dwdm+"-验证用户下载通知附件权限时候数据库异常,下载失败!");
e.printStackTrace();
return;
}
}
//通过验证
String QerrySting="select * from tzfb where id="+id;
try{
Connection conn = dbo.getConnection();
Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stat.executeQuery(QerrySting);
if(rs.next()){
String filename=rs.getString("FJWJMC");;
download_url=download_url+filename;//下载地址
File file = new File(userPath + fileSeparator + filename);//下载到下载附件的该用户的本地路径上
OutputStream fout = new FileOutputStream(file);
//ServletOutputStream sos = res.getOutputStream();
oracle.sql.BLOB blob=(oracle.sql.BLOB)((OracleResultSet)rs).getBLOB("FJ");
InputStream pi = rs.getBinaryStream("FJ");//字段名FJ
//InputStream pii=blob.getBinaryStream();
int blobsize = (int)blob.length();//?????这里可能将来不用
System.out.println("-----------blobsize-----------"+blobsize);
byte[] blobbytes = new byte[blobsize]; //照片大小0x100000
int bytesRead = 0;
while ((bytesRead = pi.read(blobbytes)) != -1)
{
//sos.write(blobbytes, 0, bytesRead);
fout.write(blobbytes, 0, bytesRead);
}
pi.close();
//sos.flush();
fout.flush();
conn.close();
System.out.println("download_url--"+download_url);
session.setAttribute("filename", filename);
forward(req,res,"/com/downloadAttachmentFile.jsp");
//res.sendRedirect(download_url);
}
}catch(Exception e){
logger.warn(dwdm+"-通知附件下载异常");
req.setAttribute("nextPage", cxp+"/form/index.jsp");
req.setAttribute("message", "下载异常,请重试或联系客服人员!");
forward(req, res, "/pub/failure.jsp");
return;
}
}
}
downloadAttachmentFile.jap:
<%@ page language="java" contentType="text/html; charset=GB2312" pageEncoding="GB2312" import="java.util.*, java.io.*, java.net.*"%>
<%
String filename = (String) session.getAttribute("filename");
String dst_fname = URLEncoder.encode(filename, "GB2312");
String dwdm=(String)session.getAttribute("userID");
ServletContext context=session.getServletContext();
String dbpath=context.getInitParameter("systemPath");
String fileSeparator = System.getProperty("file.separator");
String filepath=dbpath+fileSeparator+dwdm+fileSeparator+filename;
response.setContentType("application/octet-stream; charset=iso-8859-1");
response.setHeader("Content-disposition", "attachment; filename=\"" + dst_fname + "\"");
FileInputStream fis = null;
int byteRead;
out.clear();
try{
fis=new FileInputStream(filepath);
while ((byteRead = fis.read()) != -1) {
out.write(byteRead);
}
out.flush();
}catch(Exception e){
out.clearBuffer();
response.setContentType("text/html; charset=GB2312");
response.setHeader("Content-disposition", "inline");
out.println("<HTML><BODY><P>");
out.println(e.toString());
out.println("</P></BODY></HTML>");
}
if(fis != null){
fis.close();
}
return; // 避免下面多按了 Enter 键而输出多余的换行字元.
%>
Trackback: http://tb.donews.net/TrackBack.aspx?PostId=553888