文件的上传与下载

2023-10-17 08:25:22 浏览数 (2)

引言:平凡的生活中拥有一颗不甘于平凡的内心。

此篇文章,写的内容为文件的上传和下载,先写上传下载的位置为tomcat服务器,后期在填补位置在数据库的。

一、基于servlet实现

具体的步骤

代码语言:javascript复制
1、要有form标签,method必须=post请求
2、form标签的enctype的属性值必须为multipart/form-data
3、在form标签中使用input type=file 添加上传的文件
4、编写服务器代码接受,处理上传的数据

文件上传时发送的HTTP协议内容,摘录部分:

代码语言:javascript复制
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryTGxWXycKE3KZEeGq

enctype="multipart/form-data" 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以
二进制流的形式发送给服务器。
boundary 表示每段数据的分隔符
----WebKitFormBoundaryTGxWXycKE3KZEeGq	是由浏览器每次随机生成,就是每段数据的分界符

index.jsp

代码语言:javascript复制
演示
<h2>文件上传下载演示</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"><br>
    头像:<input type="file" name="photo"><br>
    <input type="submit" value="提交">
</form>

后端接收的时候,仅用于调试,理解

代码语言:javascript复制
// 以流的形式接收
ServletInputStream inputStream = req.getInputStream();

byte[] buffer = new byte[1024000];
int read = inputStream.read(buffer);  // 读了多少个字节
System.out.println(new String(buffer,0,read)); // 缓冲区放进来 从0开始读 read是读的长度
1、导包

commons-io commons-fileupload

创建一个maven工程,勾选模板,导入依赖

依赖如下:

代码语言:javascript复制
	<dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.4</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
	</dependency>
2、常用类和方法
代码语言:javascript复制
	ServletFileUpload类下的方法

        判断当前上传的数据格式是否是多段的格式
        boolean isMultipartContent(HttpServletRequest request)
	
	FileItem类下的方法
	
        解析上传的数据
        public List<FileItem> parseRequest(HttpServletRequest request)

        判断当前这个表单项,是否是普通的表单项,还是上传的文件类型。
            true	表示普通类型的表单项
            false	表示上传的文件类型
        boolean isFormField();

        获取表单项的name值
        String getFieldName();

        获取当前表单项的值
        String getFieldName();
	
		获取上传的文件名
		String getName();
		
		将上传的文件写到参数file所指向的磁盘位置
		void write(File file)
3、实现
代码语言:javascript复制
新建了三个类
	TestBase64		测试Base64编码
	UploadServlet	上传
	Download		下载
配置web.xml

UploadServlet.java

代码语言:javascript复制
package com;

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

import javax.servlet.ServletException;
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;

// 文件上传
public class UploadServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置页面编码 请求和响应的编码都为UTF-8 否则中文图片名上传的时候会乱码
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        System.out.println("文件上传了");
        // 1、先判断上传的数据是否是多段数据 (只有是多段的数据才是文件上传的)
        if(ServletFileUpload.isMultipartContent(req)){
            // 2、创建 FileItemFactory 工厂实现类
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            // 3、创建用于解析上传数据的工具类 ServletFileUpload
            ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
            try {
                // 4、调用解析方法,解析上传的数据,得到每一个表单项 fileItems
                List<FileItem> fileItems = servletFileUpload.parseRequest(req);
                // 循环判断,每一个表单项,是普通类型还是上传的文件
                for (FileItem fileItem : fileItems) {
                    if(fileItem.isFormField()){
                        // 普通表单项
                        System.out.println("表单项的name属性值:" fileItem.getFieldName());
                        // 参数UTF-8 解决中文乱码问题
                        System.out.println("表单项的value属性值:" fileItem.getString("UTF-8"));
                    }else{
                        // 上传的文件
                        System.out.println("表单项的name属性值:" fileItem.getFieldName());
                        System.out.println("上传的文件名:" fileItem.getName());

                        // 上传的位置  D:AllTempdata
                        fileItem.write(new File("D://AllTemp/data/" fileItem.getName()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

Download.java

代码语言:javascript复制
package com;

import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Encoder;

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;
import java.net.URLEncoder;

public class Download  extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 1、获取要下载的文件名
        String downloadFileName = "1.jpg";
        // 2、读取要下载的文件内容(通过ServletContext对象可以读取)
        ServletContext servletContext = getServletContext();

        // 获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/"   downloadFileName);
        System.out.println("下载的文件类型:" mimeType); // 下载的文件类型:image/jpeg
        // 4、在回传前,通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);
        // 5、还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
        // Content-Disposition 表示收到的数据怎么处理
        // attachment 表示附件 ,下载使用
        // filename 表示指定下载的文件名
//        resp.setHeader("Content-Disposition","attachment;filename=" downloadFileName);

        // 可支持下载中文 文件名
        // URL 解决IE和谷歌的下载 中文乱码问题
        // BASE64 解决火狐浏览器的下载 中文乱码问题
        // 设置URL编码 URL编码是把汉字转化为%xx%xx的格式
//        resp.setHeader("Content-Disposition","attachment;filename="  URLEncoder.encode("风景图片999.jpg","UTF-8"));

        // 解决火狐浏览器的下载 中文乱码问题 需要修改请求头
        // Content-Disposition: attachment;filename==?charset?B?xxxxx?=
        // =?charset?B?xxxxx?= 进行说明
        // =?       表示编码内容的开始
        // charset  字符集
        // B        表示BASE64编码
        // xxxxx    表示文件名BASE64编码后的内容
        // ?=       表示编码内容的结束
//        resp.setHeader("Content-Disposition","attachment;filename==?UTF-8?B?" new BASE64Encoder().encode("风景图片999.jpg".getBytes(    "UTF-8"))  "?=");


        // 请求头信息  进行判断 火狐或谷歌
        // User-Agent
        //	Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
        if(req.getHeader("User-Agent").contains("Firefox")){
            // 如果是火狐浏览器使用 Base64编码
            resp.setHeader("Content-Disposition","attachment;filename==?UTF-8?B?" new BASE64Encoder().encode("风景图片999.jpg".getBytes(    "UTF-8"))  "?=");
        }else {
            // 如果不是火狐  ,是谷歌或IE  使用URL编码
            resp.setHeader("Content-Disposition","attachment;filename="  URLEncoder.encode("风景图片999.jpg","UTF-8"));

        }

        // 这里放文件的路径  /斜杠被服务器解析表示 http://ip:端口号/工程名/  映射到  代码的 web目录
        // 我是在webapp下新建文件夹file  里面放了一张图片  图片名1.jpg
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/"   downloadFileName);

        // 获取响应的输出流
        ServletOutputStream outputStream = resp.getOutputStream();

        // 3、把下载的文件内容回传给客户端
        // 读取输入流中全部的数据,复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream,outputStream);




    }
}

TestBase64.java

代码语言:javascript复制
package com;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;


public class TestBase64 {
    public static void main(String[] args) throws Exception {
        String content = "这是一段中文使用base64编码的内容";
        // 创建一个Base64编码器
        BASE64Encoder base64Encoder = new BASE64Encoder();
        // 执行Base64编码操作 对字节数组进行操作
        String encode = base64Encoder.encode(content.getBytes("UTF-8"));
        System.out.println(encode); // 6L Z5piv5LiA5q615Lit5paH5L2/55SoYmFzZTY057yW56CB55qE5YaF5a65

        // 创建Base64解码器
        BASE64Decoder base64Decoder = new BASE64Decoder();
        //  解码操作
        byte[] bytes = base64Decoder.decodeBuffer(encode);
        String s1 = new String(bytes,"UTF-8");
        System.out.println(s1); // 这是一段中文使用base64编码的内容
    }
}

web.xml

代码语言:javascript复制
	<servlet>
        <servlet-name>upload</servlet-name>
        <servlet-class>com.UploadServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>upload</servlet-name>
        <url-pattern>/upload</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>download</servlet-name>
        <servlet-class>com.Download</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>download</servlet-name>
        <url-pattern>/download</url-pattern>
    </servlet-mapping>

0 人点赞