文件上传
上传文件的处理细节(1)
中文文件乱码问题
文件名中文乱码问题,可调用ServletUpLoader的setHeaderEncoding方法,或者设置request的setCharacterEncoding属性
临时文件的删除问题
由于文件大小超出DiskFileItemFactory.setSizeThreshold方法设置的内存缓冲区的大小时,Commons-fileupload组件将使用临时文件保存上传数据,因此在程序结束时,务必调用FileItem.delete方法删除临时文件。
Delete方法的调用必须位于流关闭之后,否则会出现文件占用,而导致删除失败的情况。
上传文件的处理细节(2)
文件存放位置
为保证服务器安全,上传文件应保存在应用程序的WEB-INF目录下,或者不受WEB服务器管理的目录。
为防止多用户上传相同文件名的文件,而导致文件覆盖的情况发生,文件上传程序应保证上传文件具有唯一文件名。
为防止单个目录下文件过多,影响文件读写速度,处理上传文件的程序应根据可能的文件上传总量,选择合适的目录结构生成算法,将上传文件分散存储。
上传文件的处理细节(3)
ProgressListener显示上传进度
ProgressListener progressListener = new ProgressListener() {
public void update(long pBytesRead, long pContentLength, int pItems) {
System.out.println("到现在为止, " + pBytesRead + " 字节已上传,总大小为 "
+ pContentLength);
}
};
upload.setProgressListener(progressListener);
以KB为单位显示上传进度
long temp = -1; //temp注意设置为类变量
long ctemp = pBytesRead /1024;
if (mBytes == ctemp)
return;
temp = mBytes;
文件下载
Web应用中实现文件下载的两种方式
超链接直接指向下载资源
程序实现下载需设置两个响应头:
设置Content-Type 的值为:application/x-msdownload。Web 服务器需要告诉浏览器其所输出的内容的类型不是普通的文本文件或 HTML 文件,而是一个要保存到本地的下载文件。
Web 服务器希望浏览器不直接处理相应的实体内容,而是由用户选择将相应的实体内容保存到一个文件中,这需要设置 Content-Disposition 报头。该报头指定了接收程序处理数据内容的方式,在 HTTP 应用中只有 attachment 是标准方式,attachment 表示要求用户干预。在 attachment 后面还可以指定 filename 参数,该参数是服务器建议浏览器将实体内容保存到文件中的文件名称。在设置 Content-Dispostion 之前一定要指定 Content-Type.
因为要下载的文件可以是各种类型的文件,所以要将文件传送给客户端,其相应内容应该被当做二进制来处理,所以应该调用 方法返回 ServeltOutputStream 对象来向客户端写入文件内容。
下载文件案例:
下载文件共需三个文件,两个Servlet和一个JSP页面。
ListFileServlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String filePath = this.getServletContext().getRealPath("/WEB-INF/upload");
Map fileMap = new HashMap();
traverse(new File(filePath),fileMap);
request.setAttribute("fileMap", fileMap);
request.getRequestDispatcher("/listfiles.jap").forward(request, response);
}
private void traverse(File file, Map fileMap) {
if(file.isFile()){//如果file 为文件,添加到fileMap 中去
String uuidName = file.getName();
String realName = uuidName.substring(uuidName.lastIndexOf("_")+1);
fileMap.put(uuidName,realName);
}else{//如file为目录,则递归调用
File[] subFiles = file.listFiles();
}
}
DownLoadServlet
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String uuidName = request.getParameter("uuidName");
String realName = request.getParameter("realName");
uuidName = new String(uuidName.getBytes("iso8859-1"),"utf-8");
realName = new String(uuidName.getBytes("iso8859-1"),"utf-8");
realName = URLEncoder.encode(realName,"utf-8");
System.out.println("uuidName="+uuidName);
File file = new File(getFileAddr(uuidName));
if(!file.exists()){
request.setAttribute("message", "您要下载的文件不存在");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}else{
response.setHeader("content-disposition", "attachment:filename="+realName);
FileInputStream fis = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int len =0;
while((len=fis.read(buffer))>0){
out.write(buffer,0,len);
}
fis.close();
}
}
private String getFileAddr(String uuidName){
int dir1 = uuidName.hashCode() & 0xf;
int dir2 = (uuidName.hashCode()>>4) & 0xf;
String fileAddr = this.getServletContext().getRealPath("/WEB-INF/upload")+"\\"+dir1+"\\"+dir2+"\\"+uuidName;
System.out.println("fileAddr="+fileAddr);
return fileAddr;
}
listfile.JSP
<c:forEach var="current" items="${fileMap}">
<c:url var="fileAddr" value="/servlet/DownloadServlet">
<c:param name="uuidName">${curreat.key }</c:param>
<c:param name="realName">${current.value }</c:param>
</c:url>
文件名:${current.value }
<a href="">下载</a><br/><br/>
</c:forEach>