JavaEE-Servlet-文件上传和下载

时间:2022-03-15 16:17:21

一、文件上传

1.文件上传表单(Html)

Html表单文件上传:
    <form 
        action="${pageContext.request.contextPath}/UploadServlet" 
        method="POST"
        enctype="multipart/form-data">
            <input type="text" name="desc"/>
            <input type="file" name="testFile1" />
            <input type="file" name="testFile2" />
            <input type="submit" value="上传"/>
    </form>

Http请求post格式:
    POST /xxx HTTP/1.1
    Host: x.x.x
    Content-Length: xxxxxx
    Content-Type: multipart/form-data; boundary=BoundarybXA7KWbsgAx0OB7z

    --BoundarybXA7KWbsgAx0OB7z
    Content-Disposition: form-data; name="desc"

    ...文本内容...
    --BoundarybXA7KWbsgAx0OB7z
    Content-Disposition: form-data; name="testFile1"; filename="文件1.zip"
    Content-Type: application/octet-stream

    ...文件内容...
    --BoundarybXA7KWbsgAx0OB7z
    Content-Disposition: form-data; name="testFile2"; filename="文件2.zip"
    Content-Type: application/octet-stream

    ...文件内容...
    --BoundarybXA7KWbsgAx0OB7z--

2.Servlet文件上传

方法一.使用Servlet3.0规范接口

@MultipartConfig(
    fileSizeThreshold=(可选), 内存缓冲区大小
    location=(可选), 临时文件目录,调用Part.write(..)会自动清除临时文件
    maxFileSize=(可选), 单个文件最大值, 超过则抛出IllegalStateException异常
    maxRequestSize=(可选) 总上传的最大值, 超过则抛出IllegalStateException异常
                )
public class UploadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response){
        Collection<Part> part = request.getParts();
        for (Part p : part) {
            if (p.getSubmittedFileName() == null) {
                // 非文件Part
                StringBuilder value = new StringBuilder();
                BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), "utf-8"));
                String line;
                while ((line = br.readLine()) != null) {
                    value.append(line);
                }
                System.out.println(p.getName() + ": " + value.toString());
            } else {
                // 文件Part
                String uuidName = UUID.randomUUID().toString() + "_" + p.getSubmittedFileName();
                //  参数是绝对路径+文件名,若只传文件名,则存储在location=目录
                p.write(getServletContext().getRealPath("/WEB-INF/upload")+uuidName);
            }       
        }
    }
}

方法二.使用Apache-commons-fileupload开源工具

commons-fileupload和commons-io两个包,fileupload依赖io包    
public class UploadServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response){
        if (!ServletFileUpload.isMultipartContent(request)) {
            throw new RuntimeException("请用Multipart表单上传!");
        }
        // 1.创建ServletFileUpload,设定内存缓冲区大小(默认10k),设定临时文件目录(默认操作系统临时目录)
        DiskFileItemFactory factory = new DiskFileItemFactory(100*1024,new File(xx/temp));
        ServletFileUpload fileUpload = new ServletFileUpload(factory);
        fileUpload.setFileSizeMax(1024*1024*10); // 单个文件不大于10M
        fileUpload.setSizeMax(1024*1024*100); // 总大小不大于100M
        fileUpload.setHeaderEncoding("utf-8"); // 设置编码集

        // 2.监听文件上传进度
        fileUpload.setProgressListener(new ProgressListener(){
            public void update(long bytesRead, long contentLength, int items) {
                System.out.print("当前是第" + items + "个上传项, 总大小" + length/1024f + "KB, 已经读取" + read/1024f+ "KB");      
                System.out.println();
            }
        });

        // 4.获取所有FileItem
        for (FileItem fileItem : (List<FileItem>) fileUpload.parseRequest(request)) {
            if (fileItem.isFormField()) {
                // 字符项
                String name = fileItem.getFieldName();
                String value = fileItem.getString("utf-8");
                System.out.println(name + ":" + value);
            } else {
                // 文件项
                String uuidName = UUID.randomUUID().toString() + "_" + fileItem.getName();                  
                // 生成随机目录path(目录分离)
                char[] hashPath = Integer.toHexString(uuidName.hashCode()).toCharArray();
                String path = getServletContext().getRealPath("WEB-INF/upload");
                for (char p : hashPath) path += "/" + p;
                new File(path).mkdirs();
                // 存储文件
                InputStream in = fileItem.getInputStream();
                OutputStream out = new FileOutputStream(new File(path, uuidName));
                byte[] b = new byte[100*1024];
                int len;
                while ((len=in.read(b))!=-1) {
                    out.write(b, 0, len);
                }
                // 删除临时文件
                fileItem.delete();
            }
        }
    }
}

二、文件下载

// Http响应头,要求浏览器以附件形式打开
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"utf-8"));
// MIME类型
response.setContentType(getServletContext().getMimeType(filename));

简书: http://www.jianshu.com/p/fc3198a7ea99
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/54800610
GitHub博客:http://lioil.win/2017/01/31/Servlet-File.html
Coding博客:http://c.lioil.win/2017/01/31/Servlet-File.html