文件上传、下载
文件上传
1、设置表单标签
<form action="https://localhost:8080" method="post" enctype="multipart/form-data">
    <input type="file"/>
    <input type="submit"/>
</form>
(1)enctype 属性:规定在将表单数据发送到服务器之前如何对其进行编码
(2)只有 method="post" 时才使用 enctype 属性
| 值 | 描述 | 
|---|---|
| application/x-www-form-urlencoded | 默认。在发送前对所有字符进行编码(将空格转换为 "+" 符号,特殊字符转换为 ASCII HEX 值) | 
| multipart/form-data | 不对字符编码。当使用有文件上传控件的表单时,该值是必需的 | 
| text/plain | 将空格转换为 "+" 符号,但不编码特殊字符 | 
2、encType="multipart/form-data" 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
文件上传的 HTTP 协议内容(示例)
1、请求行
2、请求头
(1)Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycl2joVsAFxzitHaW
(2)boundary 表示每段数据的分隔符
(3)WebKitFormBoundarycl2joVsAFxzitHaW 由浏览器每次都随机生成,是每段数据的分界符
3、空行
4、请求体
(1)-----WebKitFormBoundarycl2joVsAFxzitHaW 表示一段数据的开始
(2)Content-Disposition: form-datas name="username"
(3)空行
(4)当前表单项的值
(5)-----WebKitFormBoundarycl2joVsAFxzitHaW 表示另一段数据的开始
(6)Content-Disposition: form-data; name="photo"; filename="d.jpg"
(7)Content-Type: image/jpeg
(8)空行
(9)上传文件的数据
(10)-----WebKitFormBoundarycl2joVsAFxzitHaW-- 多了两个减号的分隔符,表示数据的结束标记
commons-fileupload.jar、commons-io.jar
1、ServletFileUpload 类,解析上传的数据
(1)判断当前上传数据格式是否为多段格式
public static final boolean isMultipartContent(HttpServletRequest request)
(2)解析上传数据
public List<FileItem> parseRequest(HttpServletRequest request) throws FileUploadException
2、Fileltem 接口,表示每一个表单项
(1)判断当前表单项,是普通的表单项 / 上传的文件类型:true 表示普通类型的表单项;false 表示上传的文件类型
boolean isFormField();
(2)获取表单项 name 属性值
String getFieldName();
(3)获取当前表单项的值
String getString();
String getString(String encoding) throws UnsupportedEncodingException;
(4)获取上传的文件名
String getName();
(5)将上传的文件写到 file 所指向的硬盘位置
void write(File file) throws Exception;
接收上传文件请求
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    super.doPost(req, resp);
    //判断是否为多段数据,只有多段数据才是上传数据
    if (ServletFileUpload.isMultipartContent(req)) {
        //创建FileItemFactory工厂实现类
        FileItemFactory fileItemFactory = new DiskFileItemFactory();
        //创建解析上传数据ServletFileUpload工具类
        ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
        try {
            //解析上传数据,得到每一个表单项FileItem
            List<FileItem> fileItems = servletFileUpload.parseRequest(req);
            //循环判断每一个表单项,普通类型 / 上传文件
            for (FileItem fileItem : fileItems) {
                if (fileItem.isFormField()) {
                    //普通表单项
                    System.out.println(fileItem.getFieldName());
                    //解决中文乱码
                    System.out.println(fileItem.getString("UTF-8"));
                } else {
                    //上传文件
                    System.out.println(fileItem.getFieldName());
                    System.out.println(fileItem.getName());
                    //写入磁盘
                    fileItem.write(new File("d:\\" + fileItem.getName()));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
文件下载响应(示例)
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    super.doGet(req, resp);
    //获取下载文件名
    String downloadFileName = req.getParameter("downloadFileName");
    //通过ServletContext对象,获取下载文件内容
    ServletContext servletContext = getServletContext();
    //获取下载文件类型
    String mimeType = servletContext.getMimeType("/download/" + downloadFileName);
    //回传前
    //通过响应头告知客户端返回数据类型
    resp.setContentType(mimeType);
    //通过响应头告知客户端收到数据用于下载
    //Content-Disposition 响应头,表示如何处理接收数据
    //attachment 表示附件,表示下载使用
    //filename= 表示指定下载文件名
    //URL编码把中文转换为%xxx%xxx的形式,解决中文乱码
    resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(downloadFileName, "UTF-8"));
    //以流形式返回下载文件
    InputStream resourceAsStream = servletContext.getResourceAsStream("/download/" + downloadFileName);
    //获取响应输出流
    ServletOutputStream outputStream = resp.getOutputStream();
    //读取输出流中全部数据,复制到输出流,输出到客户端
    IOUtils.copy(resourceAsStream, outputStream);
}
1、解决中文乱码
(1) URLEncoder
(2)Base64
/*
=? 表示编码内容开始
B 表示 BASE64 编码
?= 表示编码内容结束
*/
resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + new BASE64Encoder().encode(downLoadName.getBytes("UTF-8")) + "?=");
String content = "待编码内容";
//创建Base64编码器
BASE64Encoder base64Encoder = new BASE64Encoder();
//执行Base64编码操作
String encode = base64Encoder.encode(content.getBytes("UTF-8"));
//创建Base64解码器
BASE64Decoder base64Decoder = new BASE64Decoder();
//执行Base64解码操作
byte[] bytes = base64Decoder.decodeBuffer(encode);
String s = new String(bytes, "UTF-8");
(3)通过 User-Agent 使用不同方式
if (req.getHeader("User-Agent").contains("Firefox")) {
    resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" + new BASE64Encoder().encode(downLoadName.getBytes("UTF-8")) + "?=");
} else {
    resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(downloadFileName, "UTF-8"));
}
                    
                
                
            
        
浙公网安备 33010602011771号