文件的上传和下载

文件的上传和下载

一、文件的上传

实现步骤

  1. 写一个可以发送请求的jsp等前端资源页面

  2. 前端jsp中form标签中记得设置enctype,并且post请求(get有长度限制)

    代码:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
     Title
    
    
    
姓名:
头像上传:

enctype就是encodetype就是编码类型的意思。

multipart/form-data是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。

默认情况下是application/x-www-form-urlencoded

  1. 配置对应servlet

    代码:

    public class UpLoadServlet extends HttpServlet {
     @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     System.out.println("文件上传过来了啊");
     ServletInputStream is = req.getInputStream();
     byte[] buffer = new byte[1024000];
     int read = is.read(buffer);
     // read返回的是读取流的长度
     // 将inputStream中的流数据加载入byte数组buffer中
     System.out.println(new String(buffer,0,read));
     }
    }

关于上传的Http协议的介绍

image.png

使用文件解析的相关依赖

apache下的commons-fileupload.jar

  1. 导入jar包

  2. 使用jar包提供的方法即可

  3. 具体方法和类

    类:

    • ServletFileUpload类,用于解析上传的数据

    • FileItem类,表示每一个表单项

    方法:

    • boolean ServletUpload.isMultipartContent(HttpServletRequest req) 判断当前数据格式是否是多段数据的格式

    • 等等.....直接截图

图1

image.png

图2

image.png

修改后的Servlet

使用步骤:

  1. 判断是否多段数据的格式(是否为multipart / form-data)

  2. 创建FileItemFactory工厂实现类

  3. 创建解析上传数据的工具类ServletFileUpload

  4. 使用工具类ServletFileUpload方法parseRequest(request)

代码实现:

package com.GeekRose.controller;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @author Joker_Dong
 * @date 2021-10-9 12:54
 */

public class UpLoadServlet extends HttpServlet {
 @Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 System.out.println("文件上传过来了啊");
//        ServletInputStream is = req.getInputStream();
//        byte[] buffer = new byte[1024000];
//        int read = is.read(buffer);
 // read返回的是读取流的长度
 // 将inputStream中的流数据加载入byte数组buffer中
 if (ServletFileUpload.isMultipartContent(req)){
 // 是多段数据(含文件)

 // 创建FileItemFactory工厂实现类
 FileItemFactory itemFactory = new DiskFileItemFactory();
 // 创建用于上传解析上传数据的工具类
 ServletFileUpload upload = new ServletFileUpload(itemFactory);
 // 解析上传的数据 获得解析后的表单项
 try {
 List list = upload.parseRequest(req);
 // 遍历表单项
 for (FileItem fileItem : list) {
 // 先判读是否是普通的表单项
 if (fileItem.isFormField()){
 // 普通表单项
 System.out.println("表单项的name: " + fileItem.getFieldName());
 // 获取value值的时候需要设置字符集
 System.out.println("表单项的value: "+ fileItem.getString("UTF-8"));
 }else {
 // 二进制文件
 System.out.println("表单项的name: " + fileItem.getFieldName());
 System.out.println("上传文件的name: "+ fileItem.getName());

 // 写入磁盘
 fileItem.write(new File("D:\\czbk\\java io\\" + fileItem.getName()));
 }
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 }
 }
}

二、文件的下载

实现步骤

  1. 获取文件名

  2. 读取要下载的文件的内容

  3. 回传给客户端

  4. 通过响应头,告诉客户端回传的数据类型

  5. 通过响应头,告诉客户端这是用来下载的(要不直接显示了)

代码实现

package com.GeekRose.controller;

import org.apache.commons.io.IOUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;

/**
 * @author Joker_Dong
 * @date 2021-10-9 15:34
 */

public class DowmLoadServlet extends HttpServlet {
 @Override
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 System.out.println("-----doGet------");


 // 1.获取文件名
 String fileName = "abc.text";

 // 2.读取文件内容
 ServletContext servletContext = getServletContext();
 InputStream inputStream = servletContext.getResourceAsStream("/image/" + fileName);

//        byte[] buffer = new byte[1024000];
//        int read = inputStream.read(buffer);
//        System.out.println(new String(buffer,0,read));


 // 4.告诉客户端回传的数据类型
 // 先获取要下载的文件类型
 String mimeType = servletContext.getMimeType("/image/" + fileName);
 System.out.println("要下载的文件类型: "+mimeType);
 // 后通过响应头告诉客户端文件类型
 resp.setContentType(mimeType);
 // 5.告诉客户端回传的数据是用来下载的
 resp.setHeader("Content-Disposition","attachment; filename="+fileName);

 // 获取响应的输出流
 ServletOutputStream outputStream = resp.getOutputStream();
 // 3.把下载的内容回传给客户端
 // 读取输入流中的数据 复制给输出流
 IOUtils.copy(inputStream,outputStream);


 }
}

MIME:数据类型的字符串描述符

效果图:

image.png

image.png

记录:一直报错服务器500 空指针

原因:下载的图片太大了,不能使用get来下载

通过POST下载图片(数据流长度没有限制了)

/download

@Override
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 // 1.获取文件名
//        String filename = "kristen.jpg";
 String filename = req.getParameter("filename");
 System.out.println(filename);
 // 2.读取文件
 ServletContext servletContext = getServletContext();
 // 读取文件
 InputStream inputStream = servletContext.getResourceAsStream("/image/" + filename);

 // 4.通过请求头 告诉浏览器回传数据的类型
 String mimeType = servletContext.getMimeType("/image/" + filename);
 resp.setContentType(mimeType);

 // 5.通过请求头 告诉浏览器这个数据是用来下载的
 resp.setHeader("Content-Disposition","attachment; filename="+filename);

 // 3.回传数据
 IOUtils.copy(inputStream,resp.getOutputStream());

 }

download.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


 Title


下载文件

输入你要下载的图片名:
image.png

三、细节

编码问题

当我们使用传输的请求头信息中文件名设置为中文时,会出现乱码或不显示问题,因为http协议不支持中文,这里我们需要手动转换字符集

resp.setHeader("Content-Disposition","attachment; filename=女神.jpg");

效果图:

image.png

当我们手动转换字符集后:

resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode("女神.jpg","UTF-8"));

效果图:

image.png

将中文转换成16进制 %xxx%xxx的形式
方案二:

IE和Google用的URL编码,火狐使用的是BASE64编码,使用BASE64的编码和解码操作。

代码:

public class Base64Test {
 public static void main(String[] args) throws IOException {
 String content = "这是需要Base64编码的内容";
 // 1.创建编码器
 BASE64Encoder base64Encoder = new BASE64Encoder();
 // 2.编码操作
 String encode = base64Encoder.encode(content.getBytes("UTF-8"));
 System.out.println(encode);

 // 3.创建解码器
 BASE64Decoder base64Decoder = new BASE64Decoder();
 byte[] bytes = base64Decoder.decodeBuffer(encode);
 System.out.println(new String(bytes));
 }
}

显示结果:

6L+Z5piv6ZyA6KaBQmFzZTY057yW56CB55qE5YaF5a65
这是需要Base64编码的内容

使用Base64解决火狐浏览器的中文乱码问题

image.png

如果是火狐使用Base64 不是火狐使用URL编码

如何判断当前的浏览器名称?

通过请求头信息中的User-Agent字段是否含有Firefox

if (req.getHeader("User-Agent").contains("Firefox")){
 resp.setHeader("Content-Disposition","attachment; filename==?UTF-8?B?"+ new BASE64Encoder().encode("女神.jpg".getBytes("UTF-8")) +"?=");
}else {
 resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode("女神.jpg","UTF-8"));
}

在判断过后,所有浏览器就都可以解决中文乱码问题(IE、Google、Firefox)

你可能感兴趣的:(文件的上传和下载)