Servlet Java Web开发(7)上传下载

上传

先看一个例子:

有两个表单项,对应form的代码

<form action="<c:url value='/Upload1Servlet'/>" method="post" enctype="multipart/form-data">
  用户名;<input type="text" name="username"/><br/>
  照 片:<input type="file" name="zhaoPian"/><br/>
  <input type="submit" value="上传"/>
</form>

注意方法post,enctype和type="file"

下面这个上传协议内容说明了简单文本的上传。

POST /day22_1/Upload1Servlet HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*
Referer: http://pc-201706241553:8080/day22_1/form1.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/7.0)
Content-Type: multipart/form-data; boundary=---------------------------7e22e5382051c
UA-CPU: AMD64
Accept-Encoding: gzip, deflate
Host: pc-201706241553:8080
Content-Length: 469
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=474036FE3AE8CF0AE6DF94DD1F566561

-----------------------------7e22e5382051c
Content-Disposition: form-data; name="username"

helloworld
-----------------------------7e22e5382051c
Content-Disposition: form-data; name="zhaoPian"; filename="myfilename.txt"
Content-Type: text/plain

The content of the file.
the legion has returned.
and the king has returned.
The lord of the rings shall never exist.
That is the end of the sentence....
//End..
-----------------------------7e22e5382051c--
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 0
Date: Mon, 06 Aug 2018 00:44:56 GMT

说明:在请求头之后,连续两个0X0D,0X0A,然后

-----------------------------7e22e5382051c

将上传可以分为两个部分,也即是用户界面中的2个表单项

1.文本框中 username的内容

2.文件相关内容,文件名,文件类型,文件内容

 Servlet对上传文件的处理

1.打印上传的文本

request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
ServletInputStream in = request.getInputStream();
String s = IOUtils.toString(in);//该方法使用了commons-io.jar
System.out.println(s);

2.使用commons-fileupload.jar

关键API:

获取ServletFileUpload :ServletFileUpload sfu=new ServletFileUpload(new DiskFileItemFactory());

获取表单项列表List<FileItem> mylist=sfu.parseRequest(request);

其中mylist.get(0)是上面所述的普通表单项,username,

FileItem fil2=mylist.get(1)就是文件表单项,对于上传的文件,可以getContentType,getSize,getName,

最关键,保存文件,新建一个File f=new File("C;/xx.txt");

使用FileItem 的write方法保存,fil2.write(f);

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 destFile = new File("c:/baibing.jpg");
            fi2.write(destFile);
        } catch (FileUploadException e) {
            throw new RuntimeException(e);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

3.相关细节。

a,文件保存到WEB-INF目录下,比如uploads文件夹。

b.防止乱码request.setCharacterEncoding("utf-8");

c.限制上传文件大小

//在sfu.parseRequest(request);之前调用
sfu.setFileSizeMax(100 * 1024);//限制单个文件大小为100K
sfu.setSizeMax(1024 * 1024);//限制整个表单大小为1M

 如果上传文件超过size,抛出异常。FileUploadException

d.上传超大文件

此时不使用c中设置文件大小,为了防止内存被撑爆,应该设置缓存,一边读一边往硬盘里写。

DiskFileItemFactory的一个构造函数可以实现该功能,参数1为缓存大小,参数2为临时文件目录。

DiskFileItemFactory factory = new DiskFileItemFactory(20*1024, new File("F:/f/temp"));

下载

下载关键API

//指定文件名
String filename1="G:/myfile.mp4";
//使用commons-io
IOUtils.copy(new FileInputStream(filename1), resp.getOutputStream());

让浏览器弹出下载框,指定文件名。

可使用

response.addHeader("content-disposition", "attachment;filename=" + filename); 

一个完整的例子

public class Download1Servlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        
        String filename = "C:/流光飞舞.mp3";
        
        // 为了使下载框中显示中文文件名称不出乱码!
//        String framename = new String("流光%飞舞.mp3".getBytes("GBK"), "ISO-8859-1");
        String framename = filenameEncoding("流光%飞舞.mp3", req);
        
        String contentType = this.getServletContext()
                .getMimeType(filename);//通过文件名称获取MIME类型
        String contentDisposition = "attachment;filename=" + framename;
        // 一个流
        FileInputStream input = new FileInputStream(filename);
        
        //设置头
        resp.setHeader("Content-Type", contentType);
        resp.setHeader("Content-Disposition", contentDisposition);
        
        // 获取绑定了响应端的流
        ServletOutputStream output = resp.getOutputStream();
        
        IOUtils.copy(input, output);//把输入流中的数据写入到输出流中。
        
        input.close();
    }
    
    // 用来对下载的文件名称进行编码的!
    public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {
        String agent = request.getHeader("User-Agent"); //获取浏览器
        if (agent.contains("Firefox")) {
            BASE64Encoder base64Encoder = new BASE64Encoder();
            filename = "=?utf-8?B?"
                    + base64Encoder.encode(filename.getBytes("utf-8"))
                    + "?=";
        } else if(agent.contains("MSIE")) {
            filename = URLEncoder.encode(filename, "utf-8");
        } else {
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
}
原文地址:https://www.cnblogs.com/legion/p/9398474.html