文件上传和下载
文件上传/下载
上传:
表单method="post" entype="multipart/from-data"
表单中需要提交文件表单项 必须要有name属性
Servlet
当enctype="multipart/from-data" 使用 getparmeter方法就不能用了
适用 servletInputStream request.getInputStream();包含整个请求体。
上传的细节问题:
文件必须保存在web-inf下!
目的是不让浏览器直接访问到
文件名相关的问题
有的浏览器上传的文件名是绝对路径,这需要切割!c:\files\baibing.jpg
String filename=fi2.getname();
Int index=filename.lastIndexOf("\\");
If(index!=-1){
Filename=filename.substring(index+1);
}
文件名乱码或者普通表单项乱码
Request.setCharsetEncoding("utf-8");
servletFileUpload.setHeaderEncoding("utf-8");
文件同名问题 我们需要为每个文件设置一个uuid
Filename=commonUtils.uuid()+"_"+filename;
目录打散
不能在一个目录下存放之多个文件
上传文件的大小限制
单个文件大小限制
Sfu.setFileSizeMax(100*1024)//限制文件大小为100k
//必须要在获取解析之前执行
Sfu.setsizemax(1024*1024);//超出是抛出异常
整个请求所有数据大小限制
缓存大小与临时目录
package com.pcx.servlet;
import java.io.File; import java.io.IOException; import java.util.List;
import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload;
public class Upload2Servlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); DiskFileItemFactory factory=new DiskFileItemFactory(); ServletFileUpload sfu=new ServletFileUpload(factory);
try { List<FileItem>fileItemlist=sfu.parseRequest(request); FileItem fi1=fileItemlist.get(0); FileItem fi2=fileItemlist.get(1); System.out.println("普通表单项演示"+fi1.getFieldName()+"=="+fi1.getString("UTF-8")); System.out.println("文件表单项获取:"); System.out.println("Content-type:"+fi2.getContentType()); System.out.println("size"+fi2.getSize()); System.out.println("filename"+fi2.getName());
File desc=new File("D:/linghucong.jpg");//一般保存在web-Inf fi2.write(desc); } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
</head>
<body> This is my JSP page. <br> <form action="<c:url value='/Upload2Servlet'/>" method="post" enctype="multipart/form-data"> 用户名<input type="text" name="username"> 照片<input type="file" name="zhaopian"> <input type="submit" value="提交"/> </form> </body> </html> |
public class Upload3Servlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); //工厂 DiskFileItemFactory factory=new DiskFileItemFactory(); //解析器 ServletFileUpload sfu=new ServletFileUpload(factory); try { List<FileItem>list=sfu.parseRequest(request); FileItem fi1=list.get(1);
//拿到文件的根路径 String root=this.getServletContext().getRealPath("/WEB-INF/files/"); //得到文件名 处理绝对路径问题 得到hashCode值 转为16进制 使用前两个字符生成目录
String filename=fi1.getName(); int index=filename.indexOf("\\"); if(index!=-1){ filename=filename.substring(index+1); }
//添加文件的前缀问题 String savename=CommonUtils.uuid()+"_"+filename;
//得到hashcode值 int hcode=filename.hashCode(); String hex=Integer.toHexString(hcode);
//生成对应的两层结构 File dirFile=new File(root,hex.charAt(0)+"/"+hex.charAt(1)); //创建目录连 dirFile.mkdirs();
//创建目标文件 File dest=new File(dirFile,savename);
//保存 fi1.write(dest); } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }
} |
fi1.write(dest); } catch (FileUploadException e) { if( e instanceof FileUploadBase.FileSizeLimitExceededException){ request.setAttribute("msg","你上传的文件超过100k!"); request.getRequestDispatcher("/form3.jsp").forward(request, response); } } catch (Exception e) { e.printStackTrace(); }
<span>${requestScope.msg }</span> |
下载
向客户端响应字节数据。
Response.getoutputStream
两个头 一个流
Content-type mime类型
Content-disposition 默认inline
文件名乱码 问题
Firefox 使用的是base64编码
大部分的浏览器是url编码
通用方案:filename=new String (filename.getByte("GBK"),"iso-8859-1")
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String filename="D:/令狐冲.jpg"; String framename=new String(filename.getBytes("GBK"),"ISO-8859-1");
String contenttype=this.getServletContext().getMimeType(filename); String contentDisposition="attchment;filename="+framename; FileInputStream in=new FileInputStream(filename); response.setHeader("Content-Type", contenttype); response.setHeader("Content-Disposition", contentDisposition);
ServletOutputStream out=response.getOutputStream();
IOUtils.copy(in, out); in.close(); } |