文件的上传和下载

29 篇文章 0 订阅

1.文件的上传介绍

1.要有一个form标签,method=post请求
2.form标签的encType属性值必须为multipart/form-data值(以多段(每一个表单项一个数据项)的形式进行拼接,然后以二进制流的形式发给服务器)
3.在form标签中使用input type=file添加上传的文件
4.编写服务器代码(Servlet程序)接收,处理上传的数据
我们创建一个软件包,命名为com.bjpowernode,在该包下创建一个UploadServlet.java,代码如下:

package com.bjpowernode;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
        System.out.println("文件上传过来了");
    }
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        System.out.println("文件上传过来了");
    }
}

创建一个upload.jsp,代码如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="http://localhost:8080/Maven5/uploadServlet" 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>

结果如下:
在这里插入图片描述
查看Http协议,结果如下:
在这里插入图片描述
在这里插入图片描述
我们修改UploadServlet.java,代码如下:

package com.bjpowernode;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
        System.out.println("文件上传过来了");
        //因为是以二进制流传输,所有接收不到
        System.out.println(request.getParameter("username"));
        System.out.println(request.getParameter("photo"));
        ServletInputStream inputStream=request.getInputStream();
        //创建缓冲区
        byte[]buffer=new byte[1024000];
        int read=inputStream.read(buffer);
        System.out.println(new String(buffer,0,read));
    }
    @Override
    protected void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        System.out.println("文件上传过来了");
    }
}

结果如下:
在这里插入图片描述

2.commos-fileupload.jar常用API介绍说明

我们使用Tomcat10时,导入的是jakatra包,但是因为历史的原因,commons-fileupload与jakatra不兼容,所以后边我改用Tomcat8来继续接下去的内容
先在pom.xml添加commons-fileupload和commons-io依赖

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <packaging>war</packaging>

  <name>Maven6</name>
  <groupId>com.bjpowernode</groupId>
  <artifactId>Maven6</artifactId>
  <version>1.0-SNAPSHOT</version>

  <build>
    <plugins>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.7</version>
        <configuration>
          <connectors>
            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
              <port>8888</port>
              <maxIdleTime>30000</maxIdleTime>
            </connector>
          </connectors>
          <webAppSourceDirectory>${project.build.directory}/${pom.artifactId}-${pom.version}</webAppSourceDirectory>
          <contextPath>/</contextPath>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </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>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

</project>

常用的类:

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

我们修改UploadServlet.java,代码如下:

package com.bjpowernode;

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;

import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
        //System.out.println("post");
        //1.先判断上传的数据是否多段数据(只有多段数据才是文件上传的)
        if(ServletFileUpload.isMultipartContent(request)){
            //创建FileItemFactory工厂实现类
            FileItemFactory fileItemFactory=new DiskFileItemFactory();
            //创建用于解析上传数据的工具类ServletFileUpload类
            ServletFileUpload servletFileUpload=new ServletFileUpload(fileItemFactory);
            try {
                //解析上传的数据,得到每一个表单项FileItem
                List<FileItem> list = servletFileUpload.parseRequest(request);
                //循环判断,每一个表单项是普通类型还是上传的文件
                for(FileItem fileItem:list){
                    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("E:\\"+fileItem.getName()));
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

运行结果如下:
在这里插入图片描述
提交后,在控制台结果如下:
在这里插入图片描述
我们打开E盘,看见上传的文件
在这里插入图片描述

3.文件的下载

在这里插入图片描述
步骤如下:
1.获取要下载的文件名
2.读取要下载的文件内容
3.把下载的文件内容回传给客户端
4.在回传前,通过响应头告诉客户端返回的数据类型
5.还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
我们创建一个Down.java,代码如下:

package com.bjpowernode;

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

import org.apache.commons.fileupload.*;
import  org.apache.commons.io.*;

public class Download extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
        //1.获取要下载的文件名
        String downloadFileName="2.jpg";
        //2.读取要下载的文件内容(通过ServletContext对象可以读取)
        ServletContext servletContext=getServletContext();
        //获取要下载的文件类型
        String mimeType=servletContext.getMimeType("/file/"+downloadFileName);
        System.out.println("下载的文件类型"+mimeType);
        //4.在回传前,通过响应头告诉客户端返回的数据类型
        response.setContentType(mimeType);
        //5.还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
        //Content-Disposition响应头,表示受到的数据怎么处理
        //attachment表示附件,表示下载使用
        //filename表示指定下载的文件名
        response.setHeader("Content-Disposition","attachment;filename="+downloadFileName);
        //斜杆被服务器解析表示为http://ip:port/工程名/ 映射到代码的webapp目录
        InputStream resourceAsStream=servletContext.getResourceAsStream("/file/"+downloadFileName);
        //获取响应的输出流
        OutputStream outputStream=response.getOutputStream();
        //读取输入流中全部的数据,复制给输出流,回传给客户端
           //3.把下载的文件内容回传给客户端IOUtils.copy(resourceAsStream,outputStream);
    }
}

添加web.xml配置,然后在webapp目录下创建一个file目录,在file目录下有2.jpg图片
结果如下:
显示的图片如下:
在这里插入图片描述
在这里插入图片描述
如果我们传输要下载的文件名含有中文字符,如果使用的是谷歌浏览器或IE浏览器,需要修改代码,修改代码如下:

//URL编码是把汉字转换成xx%xx的格式
        response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("中国.jpg","UTF-8"));

如果是火狐浏览器,因为火狐浏览器支持的是Base64编码,故上述方法无效。我们先创建一个Test.java来展示该解码方式,代码如下:

 public static void main(String[]args)throws Exception{
        String content="这是需要Base64编码的内容";
        //创建一个Base64编码器
        BASE64Encoder base64Encoder=new BASE64Encoder();
        //执行Base64编码操作
        String encodedString=base64Encoder.encode(content.getBytes("UTF-8"));
        System.out.println(encodedString);
        //创建Base64解码器
        BASE64Decoder base64Decoder=new BASE64Decoder();
        //解码操作
        byte[] bytes=base64Decoder.decodeBuffer(encodedString);
        String str=new String(bytes,"UTF-8");
        System.out.println(str);
    }

回归主题,对于火狐浏览器,想要下载文件名带有中文的文件,需要修改代码如下:

response.setHeader("Content-Disposition","attachment;filename==?UTF-8?B?"+new BASE64Encoder().encode("中国.jpg".getBytes("UTF-8"))+"?=");

根据浏览器动态切换要修改的代码

if(request.getHeader("User-Agent").contains("Firefox")){
            //如果是火狐浏览器使用Base64编码
            response.setHeader("Content-Disposition","attachment;filename==?UTF-8?B?"+new BASE64Encoder().encode("中国.jpg".getBytes("UTF-8"))+"?=");
        }else{
            //URL编码是把汉字转换成xx%xx的格式
            response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("中国.jpg","UTF-8"));
        }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值