Java—文件的上传和下载

本文详细介绍了文件上传的表单构造、服务器接收与解析,以及如何使用commons-fileupload和commons-io库。还涵盖了文件下载的实现,包括响应头设置和解决中文乱码问题。涵盖的关键技术包括multipart/form-data、ServletFileUpload和文件名编码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


文件的上传和下载是非常常见的功能,在很多的系统或软件中都经常使用到。
例如:QQ头像的上传、邮箱中邮件的发送和接收、在浏览器中下载资源文件等等

一、文件上传

1、文件上传的介绍

1、创建一个form表单标签,设置method=post请求
2、from表单的encType属性值必须为multipart/form-data
3、在form标签中使用input type=file进行文件的添加
4、编写服务器代码接收并处理上传的文件

下面我们用代码演示该如何进行文件的上传

(1)up_file.jsp页面,用于上传文件

multipart/form-data:表示提交的数据以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发上给服务器

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="upFileServlet" method="post" enctype="multipart/form-data">
        用户名:<input type="text" name="username"><br/>
        头像:<input type="file" name="photo"><br/>
        <input type="submit" value="上传">
    </form>
</body>
</html>

(2)UpFileServlet类,用于接收客户端发来的请求

public class UpFileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.println("文件上传成功");
    }
}

(3)web.xml文件

<servlet>
    <servlet-name>UpFileServlet</servlet-name>
    <servlet-class>servlet.UpFileServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>UpFileServlet</servlet-name>
    <url-pattern>/upFileServlet</url-pattern>
</servlet-mapping>

向表单中填入数据并上传文件,然后我们在服务器端使用req.getParameter()方法获取数据时,无法获得。我们在前面说过multipart/form-data是以流的形式进行传输数据的,而我们的from表单正是用的这种形式,所以我们也应该用流的形式进行接收
在这里插入图片描述
在这里插入图片描述
以流的形式进行数据的接收并输出

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

这里的 123456 是用户名的值,123123 是1.txt文件中的数据
在这里插入图片描述

2、上传文件的解析

(1)引入第三方的工具类commons-fileupload和commons-io

第一种方式,使用maven工程,在pom.xml文件中引入两个外部文件

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.4</version>
</dependency>

第二种方式是引入两个外部类的jar包

官网地址: http://commons.apache.org/proper/commons-fileupload/

(2)工具类中常用的类和方法

作用
FIleItem类表示每一个表单项
ServletFileUpload类用于解析上传的数据

方法

方法作用
boolean ServletFileUpload.isMultipartContent(HttpServletRequest request)判断当前上传文件的数据格式是否是多段的
List<FileItem> parseRequest(HttpServletRequest request)解析上传的数据
boolean FileItem.isFormField()判断当前这个表单项是否是普通的表单项还是上传的文件类型的表单项
true表示普通的表单项
false表示文件类型的表单项
String FileItem.getFieldName()获取表单项的name属性值
String FileItem.getString()获取表单项的值
String FileItem.getName()获取上传的文件名
void FileItem.write(file)将上传的文件写到参数file所指向的磁盘的位置

(3)文件的上传

UpFileServlet类

public class UpFileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1、判断上传的数据是否是多段数据的形式(当其是多段数据时可以得出它是文件的上传)
        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("表单项的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());
                        // 将上传文件保存到磁盘上
                        fileItem.write(new File(("C:\\Users\\Administrator\\IdeaProjects\\springmvc\\java_web-fileup_down\\src\\main\\webapp\\file\\") + fileItem.getName()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

在浏览器中填写表单信息并提交,可以看到在控制台输出的表单的信息,以及1.txt文件被保存到了file目录下,说明文件上传成功了
在这里插入图片描述
在这里插入图片描述

二、文件下载

1、文件下载的介绍

客户端(浏览器):

向服务器发送请求表示要下载某个资源文件

服务器:

1、获取客户端要下载的文件名
2、读取要下载的文件的内容
3、通过响应头告诉客户端返回的数据的类型和数据是用于下载使用的
4、把要下载的文件内容回传给客户端

2、文件下载的实现

(1)创建DownFileServlet类,处理文件下载

public class DownFileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、获取客户端要下载的文件名(自定义)
        String fileName = "1.txt" ;
//        2、读取要下载的文件的内容(通过ServletContext对象读取)
        ServletContext servletContext = getServletContext();

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

        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + fileName);
        // 获取响应的输出流
        ServletOutputStream outputStream = resp.getOutputStream();
        // 4、读取输入流中数据复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream,outputStream) ;
    }
}

(2)结果

我们先从up_file.jsp页面上传过数据后,然后用浏览器去访问downFileServlet程序时,它会直接将该文件下载
在这里插入图片描述

3、解决文件名中文乱码

当我们将文件名改为中文时,再去访问servlet程序,发现下载的文件的文件名出现了中文乱码的情况
在这里插入图片描述

resp.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(fileName,"utf-8"));

设置响应头中的URL编码为utf-8,再次访问下载文件,可以看到文件名没出现乱码
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值