JavaEE-Servlet-文件上传和下载

一、文件上传

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容