1. 文件上传
浏览器在上传的过程中是将文件以 二进制的流 的形式提交到服务器端.
1 准备一个form表单,里面有一个上传,form表单的类型必需是multipart/form-data
2 准备一个上传的Servlet,到后台接收传过来的普通表单数据 与 文件(二进制)
3 导入相应的FileUpload jar包 (commons-fileupload-1.2.2.jar ,commons-io-1.4.jar)
重要:上传时,我们表单的请求类型必需设置成multipart/form-data . 上传的method必需是POST的
完成文件上传重要方法:fileItem.write(File file);
FileItemd对象就是从request中获得数据对象,通过调用它的write把其中的数据写入到磁盘文件(File file)
常见问题及其解决方案:
1. 上传文件对象封装----CFile对象 ,可以解决 多个文件上传 及其对应属性的属性很多问题。
2. FileUtil.java 工具类 虽然可以完成上传 但是 拿不到普通表单字段值,文件上传后,我们拿到不到上传的文件的数据。
解决办法:准备两个容器(就是集合),然后一个容器装普通表单,另一个容器装上传的文件数据。把这个容器交给工具类,工具类拿到相应的数据后将数据放回到容器中。
1. 项目整体架构:
2. register.jsp代码
<body> <form action="UploadServlet" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="username"/><br> 密码:<input type="password" name="password"/><br> 头像1:<input type="file" name="headImg1"/><br> 头像2:<input type="file" name="headImg2"/><br> <input type="submit" value="提交"/> </form> </body>
3. UploadServlet.java代码
package com.gs.controller; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; 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.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.FilenameUtils; import com.gs.domain.CFile; import com.gs.tools.FileUtil; @WebServlet("/UploadServlet") public class UploadServlet extends HttpServlet { protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { Map<String, String> fieldMap = new HashMap(); Map<String,CFile> filesMap = new HashMap(); FileUtil.upload(request, fieldMap, filesMap); //拿数据 System.out.println(fieldMap); System.out.println(filesMap); } catch (Exception e) { request.setAttribute("message","类型不匹配"); request.getRequestDispatcher("register.jsp").forward(request, response); } } }
4. CFile.java代码
package com.gs.domain; public class CFile { private String filename; private String filepath; public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } public String getFilepath() { return filepath; } public void setFilepath(String filepath) { this.filepath = filepath; } @Override public String toString() { return "CFile [filename=" + filename + ", filepath=" + filepath + "]"; } }
5. FileUtil.java 工具类代码
package com.gs.tools; import java.io.File; import java.net.URLDecoder; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletRequest; 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; import org.apache.commons.io.FilenameUtils; import com.gs.domain.CFile; public class FileUtil { //准备只支持的图片类型 private static final String[] IMG_TYPE = {"jpg","png","gif","bmp"}; public static void upload(HttpServletRequest request, Map<String,String> fieldMap, Map<String,CFile> filesMap) { //判断是否有一个文件上传的请求 boolean isMultipart = ServletFileUpload.isMultipartContent(request); if(isMultipart){ //为基于磁盘的文件项创建工厂,并创建一个新的文件上传对象 DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); upload.setFileSizeMax(1024*1024*2);//单个文件最大2M upload.setSizeMax(1024*1024*5); //所有文件的请求的大小 5M try { //拿到每一项表单控件组成的 FileItem类型的集合 List<FileItem> items = upload.parseRequest(request); for (FileItem fileItem : items) { System.out.println(fileItem); //如果是一般表单,用一般表单的处理方式 if(fileItem.isFormField()) { //表单控件name的名称 String filedName = fileItem.getFieldName(); //表单控件name名称对应的值 String value = fileItem.getString("UTF-8"); //value = new String(value.getBytes("ISO-8859-1"),"utf-8");//也可以解决乱码问题 fieldMap.put(filedName, value);//将键值对添加到集合内 }else{//如果是文件上传的控件 //获取文件名,使用工具类:FilenameUtils解决ie浏览器拿文件全路径名的问题 String name = FilenameUtils.getName(fileItem.getName()); //获取后缀名 String ext = FilenameUtils.getExtension(name); //验证后缀名是否满足图片类型 if(Arrays.asList(IMG_TYPE).contains(ext)) { String randomUUID = UUID.randomUUID().toString(); //(通过upload文件夹)获取项目下的存储资源的路径 // F:workspace.metadata...文件上传\upload String path = request.getServletContext().getRealPath("/upload"); path = path.substring(0, path.indexOf(".metadata")); String pa = request.getContextPath(); //项目的上下文路径,这里获取的是乱码 pa = URLDecoder.decode(pa,"utf-8");//解码 System.out.println(pa); path=path.replace('/', '\')+pa+"\WebContent\upload"; System.out.println(path); //创建文件对象 File file = new File(path, randomUUID+"."+ext); //将二进制流写入文件对象中 fileItem.write(file); CFile cfile = new CFile(); cfile.setFilename(randomUUID+"."+ext); cfile.setFilepath(file.getAbsolutePath()); filesMap.put(randomUUID+"."+ext,cfile); }else { throw new RuntimeException("文件类型不符合"); } } } }catch (RuntimeException e) { throw e; } catch (Exception e) { e.printStackTrace(); } } } }
2. 文件下载
文件下载可以有两种方法:
1. 超连接直接下载功能
2. 使用java代码经过servlet来进行下载
1. download.jsp代码
<body> <p style="color:red"> 超连接直接下载功能 </p> <a href="download/俄罗斯方块.html" download="俄罗斯方块">俄罗斯方块.html</a><br /> <a href="download/金玟岐 - 岁月神偷.mp3" download="岁月神偷">金玟岐 - 岁月神偷.mp3</a><br /> <a href="download/fun.mp4" download="fun视频">fun.mp4</a><br /> <a href="download/2.jpg" download="二次元图片">2.jpg</a><br /> <p style="color:red"> 使用java代码经过servlet来进行下载 </p> <a href="DownloadServlet?filename=俄罗斯方块.html">俄罗斯方块.html</a><br /> <a href="DownloadServlet?filename=金玟岐 - 岁月神偷.mp3">金玟岐 - 岁月神偷.mp3</a><br /> <a href="DownloadServlet?filename=fun.mp4">fun.mp4</a><br /> <a href="DownloadServlet?filename=2.jpg">2.jpg</a><br /> </body>
2. DownloadServlet.java代码
package com.gs.controller; import java.io.File; import java.io.IOException; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.file.Files; import java.nio.file.Paths; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/DownloadServlet") public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String pa = request.getContextPath(); //项目的上下文路径,这里获取的是乱码 pa = URLDecoder.decode(pa,"utf-8");//解码 String filename = request.getParameter("filename"); String path = request.getServletContext().getRealPath("/download"); path = path.substring(0, path.indexOf(".metadata")); System.out.println(path); //F:workspace path=path.replace('/', '\')+pa+"\WebContent\download"; System.out.println(path); //F:workspace/文件上传和下载WebContentdownload //将指定路径的文件绑定成File对象 File file = new File(path,filename); //设置浏览器不能直接打开文件 response.setContentType("application/x-msdownload"); //解决浏览器下载文件没有后缀名和文件名问题 String userAgent = request.getHeader("User-Agent"); if(userAgent.contains("MSIE")) { //IE浏览器 filename = URLEncoder.encode(filename,"UTF-8"); }else { //其他浏览器 filename = new String(filename.getBytes("UTF-8"),"ISO-8859-1"); } response.setHeader("Content-Disposition","attachment;filename="+filename); //将文件以流的形式输出到页面中下载 Files.copy(Paths.get(file.getAbsolutePath()), response.getOutputStream()); } }
页面显示: