页面的设置:
- 必须使用表单,而不能是超链接;
- 表单的method必须是POST,而不能是GET;
- 表单的enctype必须是multipart/form-data(字符);默认值: application/x-www-form-urlencoded(字节)
- 在表单中添加file表单字段,即<input type=”file”…/>文件域
<form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="username"/><br/> 文件1:<input type="file" name="file1"/><br/> 文件2:<input type="file" name="file2"/><br/> <input type="submit" value="提交"/> </form>
后台的要求:
1、导入jar包、commons-fileupload.jar,核心包; commons-io.jar,依赖包。
2、request.getParameter(String)方法失效:获取指定的表单字段字符内容,
但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
fileupload简单应用
fileupload的核心类有:DiskFileItemFactory、ServletFileUpload、FileItem。
- 创建工厂类DiskFileItemFactory对象:DiskFileItemFactory factory = new DiskFileItemFactory()
- 使用工厂创建解析器对象:ServletFileUpload fileUpload = new ServletFileUpload(factory)
- 使用解析器来解析request对象:List<FileItem> list = fileUpload.parseRequest(request)
常用方法:
- String getName():获取文件字段的文件名称;***
- String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
- String getFieldName():获取字段名称,例如:<input type=”text” name=”username”/>,返回的是username;
- String getContentType():获取上传的文件的类型,例如:text/plain。
- int getSize():获取上传文件的大小;
- boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
- InputStream getInputStream():获取上传文件对应的输入流;
- void write(File):把上传的文件保存到指定文件中。
上传文件的细节处理
1、把上传的文件放到WEB-INF目录下
如果没有把用户上传的文件存放到WEB-INF目录下,那么用户就可以通过浏览器直接访问上传的文件,这是非常危险的。
通常我们会在WEB-INF目录下创建一个uploads目录来存放上传的文件,而在Servlet中找到这个目录需要使用ServletContext的getRealPath(String)方法,例如在我的upload1项目中有如下语句:
ServletContext servletContext = this.getServletContext();
String savepath = servletContext.getRealPath(“/WEB-INF/uploads”);
其中savepath为:F: omcat6_1webappsupload1WEB-INFuploads。
2、中文乱码问题
fileItem.getString(“utf-8”)来处理编码
3、上传文件同名问题
当前毫秒值
//得到上传文件的文件名 String fileName = fileItem.getName(); //得到后缀名 String subfix = fileName.substring(fileName.lastIndexOf(".")); //获取当前毫秒值 long timer = new Date().getTime(); //写入文件 fileItem.write(new File(savePath+"/"+timer+subfix));
使用UUID
//定义文件夹位置 String savePath = "d:/upload/"; //使用uuid随机保存文件名(去除中间的-,全部变为大写) String fileName = UUID.randomUUID().toString() .replace("-","").toUpperCase(); //后缀名 String uploadFileName = fileItem.getName(); String sufix = uploadFileName.substring(uploadFileName.lastIndexOf(".")); //写入文件 fileItem.write(new File(savePath+fileName+sufix));
4、上传的单个文件的大小限制
ServletFileUpload类的setFileSizeMax(long)
FileUpload.setFileSizeMax(1024*10)表示上限为10KB(推荐)
上传的文件超出了上限,那么就会抛出FileUploadBase.FileSizeLimitExceededException异常 if(e instanceof FileUploadBase.FileSizeLimitExceededException) { // 在request中保存错误信息 request.setAttribute("msg", "上传失败!上传的文件超出了10KB!");
总大小限制fileUpload.setSizeMax(1024 * 10);(不推荐)
代码:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { //1.创建工厂对象 DiskFileItemFactory factory = new DiskFileItemFactory(); //2.由工厂对象得到ServletFileUpload对象 ServletFileUpload fileUpload = new ServletFileUpload(factory); //限制上传文件大小 //fileUpload.setFileSizeMax(300*1024); //3.解析request对象 try { List<FileItem> fileItems = fileUpload.parseRequest(request); //4.遍历List集合 for (FileItem fileItem : fileItems) { //判断fileItem是否是一个文件域 //boolean isFormField() true 不是一个文件域 false 是一个文件域 if(fileItem.isFormField()){ // 不是一个文件域 //获取input的name getFieldName() String name = fileItem.getFieldName(); //获取input的value getString(编码) String value = fileItem.getString("UTF-8"); }else{//文件域表单
将文件保存到服务器硬盘、在WebContent创建一个upload目录(服务器重启数据丢失)
}else{//文件域表单 //保存到服务器硬盘 //1)保存到项目发布的目录 //a.得到上传文件的文件名 getName() xxx.jpg String fileName = fileItem.getName(); //得到后缀名 String subfix = fileName.substring(fileName.lastIndexOf(".")); if(".jpg".equals(subfix) || ".png".equals(subfix) || ".gif".equals(subfix)){ //b.把文件保存到硬盘 FileItem# void write(java.io.File file) //File对象对应的文件, 不能是文件夹 //ServletConfig // 这个项目发布的文件夹的路径, 通过ServletContext对象的getRealPath() String savePath = this.getServletContext().getRealPath("/upload"); // 取文件名两种策略: 1) 当前系统的毫秒值 long timer = new Date().getTime(); fileItem.write(new File(savePath+"/"+timer+subfix)); }else{ }
将文件保存到硬盘任意的目录(推荐)
String savePath = "d:/upload/"; //使用uuid随机保存文件名 String fileName = UUID.randomUUID().toString() .replace("-","").toUpperCase(); //后缀名 String uploadFileName = fileItem.getName(); String sufix = uploadFileName.substring(uploadFileName.lastIndexOf(".")); //写入服务器硬盘目录 fileItem.write(new File(savePath+fileName+sufix));
数据库中保存文件名,(当前毫秒值/UUID+后缀名)
页面展示图片数据
<img src="/img/ ${photoPath} " />
D: omcatapache-tomcat-7.0.82webappsles18 --> /les18 映射
/项目名 对服务器硬盘某个路径的映射
/img -->d:upload (eclipse 配置虚拟的文件路径)
1、
2、
其他开发工具需要自己手动添加
<Context docBase="D:upload" path="/img" reloadable="true"/></Host>
添加数据包含头像的servlet代码
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1、创建工厂 DiskFileItemFactory factory = new DiskFileItemFactory(); //2、通过工厂对象创建servletFileUpload对象,上传对象 ServletFileUpload fileUpload = new ServletFileUpload(factory); //3、解析request对象FileItem List<FileItem> fileItems; try { fileItems = fileUpload.parseRequest(request); //创建一个客户对象 Client c = new Client(); for (FileItem fileItem : fileItems) { if(fileItem.isFormField()){ //返回true表示非文件域,获取value值 if("cname".equals(fileItem.getFieldName())){ c.setCname(fileItem.getString("UTF-8")); } if("gender".equals(fileItem.getFieldName())){ c.setGender(fileItem.getString("UTF-8")); } if("birthday".equals(fileItem.getFieldName())){ c.setBirthday(fileItem.getString("UTF-8")); } if("cellphone".equals(fileItem.getFieldName())){ c.setCellphone(fileItem.getString("UTF-8")); } if("email".equals(fileItem.getFieldName())){ c.setEmail(fileItem.getString("UTF-8")); } if("description".equals(fileItem.getFieldName())){ c.setDescription(fileItem.getString("UTF-8")); } }else{ //false表示保存文件域 //保存文件 String savePath = "d:/upload/"; //使用uuid随机保存文件名 String fileName = UUID.randomUUID().toString() .replace("-","") .toUpperCase(); //后缀名 String uploadFileName = fileItem.getName(); String sufix = uploadFileName.substring(uploadFileName.lastIndexOf(".")); //写入服务器硬盘目录 fileItem.write(new File(savePath+fileName+sufix)); //给Client对象的photopath属性赋值,文件名 c.setPhotoPath(fileName+sufix); } } //调用业务层获取数据 ClientService cs = new ClientServiceImpl(); boolean b = cs.insert(c); if(b){ request.setAttribute("msg", "添加成功"); }else{ request.setAttribute("msg", "添加失败"); } //转发执行结果页面 request.getRequestDispatcher("/msg.jsp").forward(request, response); } catch (FileUploadException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }
页面显示代码
<td> <img src=" <c:choose> <c:when test="${empty client.photoPath }">./images/photo.jpg</c:when> <c:otherwise>/img/${client.photoPath}</c:otherwise> </c:choose> " width="60" height="60" /> </td>