首页 > 其他分享 >文件的上传和下载

文件的上传和下载

时间:2023-09-23 22:56:22浏览次数:46  
标签:文件 上传 Base64 import servlet javax 下载

文件的上传

  • 1.我们先测试打通服务器
  • upload.jsp负责文件的上传
<%--
  Created by IntelliJ IDEA.
  User: SWT
  Date: 2023/9/22
  Time: 18:39
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <form action="http://localhost:8080//jsp//uploadServlet"  method="post" enctype="multipart/form-data">
      姓名:<input type="text" name="username"><br>
       头像:<input type="file" name="photo"><br>
        <input type="submit" value="上传">


    </form>
</head>
<body>

</body>
</html>

  • 我们使用UploadServlet程序进行接收:
package com.servlet;

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

public class UploadServlet extends HttpServlet {
   //用来出来上传的文件
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("文件上传过来了");
    }
}

  • doPost方法被访问,说明数据可以发送到servlet程序

文件上传的Http协议介绍

  • 在请求时
  • 请求头:
  • 请求体
  • 为什么用Post请求
    因为get请求是有长度限制的,而上传文件一般都会超出get的长度限制

    我们的客户端是以流的形式发送数据的,所以我们服务器必须以流的形式来接收数据
  • 以流的形式来接收数据:
  • 新的servlet程序
package com.servlet;

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.IOException;

public class UploadServlet extends HttpServlet {
   //用来出来上传的文件
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       // System.out.println("文件上传过来了");
        final ServletInputStream inputStream = req.getInputStream();
        byte[]buffer = new byte[1024000];
        final int read = inputStream.read(buffer);
        System.out.println(new String(buffer,0,read));


    }
}

  • 输出

上传用到的类和方法的介绍

  • 根据上面我们已经可以接收到文件的数据了,现在我们需要的是将数据解析得到我们需要的内容

  • 对于文件上传这些常见的功能,有很多第三方机构已经写好了,并且封装成了jar包,我们只需要区使用就可以了

  • 1.我们首先需要导入我们需要的2个jar包(在资料里面有)
    我们上传的表单项的类型不同,对应的我们的处理也不同(如普通表单项和文件)

对于具体的类和方法的介绍,详见官方笔记

使用fileupload解析上传数据

  • 注意:
  • jsp文件中的表单项
 <form action="http://localhost:8080//jsp//uploadServlet"  method="post" enctype="multipart/form-data">
      姓名:<input type="text" name="username"><br>
       头像:<input type="file" name="photo"><br>
        <input type="submit" value="上传">
  

    </form>
  • servlet程序
package com.servlet;

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;

public class UploadServlet extends HttpServlet {
   //用来出来上传的文件
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

      //1.判断上传的数据是否是多段数据(只有是多段数据,才是文件上传的)
        if(ServletFileUpload.isMultipartContent((req))){
            //创建FileItemFactory工厂实现类
            FileItemFactory factory = new DiskFileItemFactory();
            //创建用于解析上传数据的工具类ServletFileUpload类的对象
            ServletFileUpload servletFileUpload = new ServletFileUpload(factory);

            try {
                //解析上传的数据,得到每一个表单项FileItem
                final List <FileItem>list = servletFileUpload.parseRequest(req);
                //循环判断,每一个表单项:是普通类型还是上传的文件
                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());
                        //将上传的文件写入到d盘的一个位置
                        fileItem.write(new File("d://"+fileItem.getName()));
                    }
                }
            } catch (FileUploadException e) {
               e.printStackTrace();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }


    }
}

  • 输出

文件下载

文件下载的实现

  • 关于文件下载过程:

  • 从上面我们可以看出,文件下载需要首先客户端发送请求,然后服务器进行处理:服务器会在服务器的存储系统中找到相应的文件。并以二进制的形式将文件返回给客户端。然后由客户端进行下载

  • 我们省略客户端,直接以访问servlet的形式进行演示

  • 步骤分析:

  • servlet程序
package com.servlet;

import org.apache.commons.io.IOUtils;

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

//处理下载图片
public class DownLoadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

     //1.获取要下载的文件名
        String downloadFileName = "小姐姐.jpg";
        //2.读取要下载的文件内容(通过ServletContext对象可以读取)
        /*
        *斜杠被服务器解析为http://localhost:8080/工程名/
        * 映射到web目录
         */

        final ServletContext servletContext = getServletContext();
        final InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
        //4.在回传前,通过响应头告诉客户端返回的数据类型
        //获取要下载的文件类型
        final String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
        System.out.println("下载的文件类型"+mimeType);
      //告诉客户端返回的数据类型
        resp.setContentType(mimeType);
        //5.告诉客户端收到的数据用于下载使用(还是使用响应头)
        //Content-Disposition响应头  ,表示收到数据怎样处理
        //attachment,表示附件,表示下载使用
        //filename表示指定下载的文件名
        resp.setHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
        //获取输出流
        final ServletOutputStream servletOutputStream = resp.getOutputStream();
        //3.把下载的文件内容回传给客户端
       //读取输出流中的全部数据,复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream, servletOutputStream);






    }
}

我们的步骤4 5 需要在把下载的文件内容回传给客户端之前完成。

  • 我的文件名小姐姐.jpg是中文名。好像在下载的文件中中文名并没有显示。似乎是还存在中文乱码的问题

使用URLEncoder解决谷歌和IE浏览器中文下载名乱码的问题

  • 下载的文件名是由由设置的响应头决定的,可以和原来的文件名相同,也可以不同
    当我们 下载的文件名是中文的话,我们的下载的文件的名字,是不能展现的
  • 我们看看http协议里面的内容


因为http协议是老美设计的,在最初的时候仅仅考虑了英文的情况,没有考虑到中文的情况

使用URLEncoder类将中文进行URL编码。将中文转化为%xx%xx(16进制)的格式。已解决中文乱码的问题

  • 此时我们再次查看协议内容

    此时我们下载的文件的中文文件名也可以显示了
  • 但是好像通过上面的编码解决中文的问题,但是我们的火狐浏览器还是不支持URL编码

Base64编码操作

现在一般推荐使用Base64类直接进行编码和解码,而不去使用sun.misc.BASE64Encoder类

package com.test;

import java.util.Base64;
import java.util.Scanner;

public class Test2 {

//演示Base64的编码和解码
    public static void main(String[] args) {
        //编码操作
        String content = "使用Base64进行编码和解码";
        final Base64.Encoder encoder = Base64.getEncoder();
        final byte[] encode = encoder.encode(content.getBytes());
        System.out.println(encode.toString());
        //解码操作
        final Base64.Decoder decoder = Base64.getDecoder();
        final byte[] decode = decoder.decode(encode);
        System.out.println(new String(decode));

    }
}

使用Base64编码解决解决火狐浏览器下载(附件)中文乱码问题


目前我的IDEA上面提供Base64编码的类是Base64类,但是我们按照上面的写法无法达到相同的需求

使用 User-Agent请求头判断:动态切换不同的方案解决所有浏览器附件乱码的问题

  • 基本思路:如果是火狐浏览器使用Base64编码,如果是IE,谷歌使用URL编码
  • 在请求头中:有个User-Agent表示浏览器的信息

总结

1.在文件的下载阶段使用了URL和Base64两种方式来应对不同的浏览器来解决中文附件名乱码的问题。但是IDEA已经没有提供Base64EnCoder类来编码了。而是提供了Base64类,使用了Base64类但是采用Base64Encoder类的回应头的写法,好像不能生效
2.但是好像目前的火狐浏览器也可以兼容URL的编码方式了,所以我认为没有必要进行浏览器判断来选择不同的编码方式了,而是可以直接都使用URL的编码方式就可以了

标签:文件,上传,Base64,import,servlet,javax,下载
From: https://www.cnblogs.com/swtaa/p/17722304.html

相关文章

  • Windows文件及目录操作
    Windows文件及目录操作1.2.3.......
  • excel文件未保存进行关闭找回历史记录
    https://m.baidu.com/sf?pd=topone_trustpaper&resource_id=55858&word=excel%E6%96%87%E6%A1%A3%E6%9C%AA%E4%BF%9D%E5%AD%98%E6%80%8E%E4%B9%88%E5%8A%9E&ext=%7B%22url%22%3A%22https%3A%5C%2F%5C%2Fyingyongge.com%5C%2Fw5C5.html%22%2C%22srcid%22%3A%222842......
  • Hadoop是什么? Hadoop是一个由Apache开发的开源分布式计算框架,它能够处理大规模数据并
    Hadoop是什么?Hadoop是一个由Apache开发的开源分布式计算框架,它能够处理大规模数据并行处理任务,支持大规模数据存储和处理。Hadoop的核心组件包括分布式文件系统HDFS和分布式计算框架MapReduce,它们使得Hadoop可以在廉价的硬件上并行地处理大量数据。Hadoop还包括很多相关的项目和子......
  • Redis 下载和安装(Windows)教程
    下载虽然Redis官方网站没有提供Windows版的安装包,但可以通过GitHub来下载Windows版Redis安装包。下载地址:https://github.com/tporadowski/redis/releases打开上述的下载链接,Redis支持32位和64位的Window系统,如图所示:下载完成后,解压压缩包,您会看到如下图......
  • 大文件上传之--切片上传和断点续传
    <template>  <div id="app">    <el-upload      drag      action      :auto-upload="false"      :show-file-list="false"      :on-change="changeFile"    >      <i class="el-icon-upload"&g......
  • 在 Shell命令中,通常会使用通配符表达式来匹配一些文件
    #在Shell命令中,通常会使用通配符表达式来匹配一些文件*,?,[],{}例:字符含义实例匹配0或多个字符a*ba与b之间可以有任意长度的任意字符,也可以一个也没有,如aabcb,axyzb,a012b,ab。?匹配任意一个字符......
  • Linux文件管理学习感悟与笔记
    1.文件目录与路径 绝对路径与相对路径的区别绝对路径:路径的写法,由根目录/写起,例如:/usr.share/doc这个目录相对路径:路径的写法,不是由/写起,例如由/usr/share/doc要到/usr/share/man底下时,可以写成:cd../man这就是相对路径的写法2.目录与文件操作处理目录的常用命......
  • Ubuntu中文件编译时gcc的链接参数-lm
    在Terminal中使用gcc编译.c文件时,本以为参数的位置是十分宽松的,比如 -o目标名 与 编译条件 是可以互换位置的。正如此例:将hello.c文件编译成可执行文件hello时,gcc-ohellohello.c与gcchello.c-ohello两条编译命令是等价的。但当遇到代码文件中遇到数学函数时,在......
  • 如何使用python进行pdf文件分割
    1.安装PyPDF2包pipinstallPyPDF2然后importPyPDF22.在PyPDF2库中,可以使用以下代码打开PDF文件:pdf_file=open('filename.pdf','rb')pdf_reader=PyPDF2.PdfFileReader(pdf_file)total_pages=pdf_reader.numPages3.下面代码将每一页分开fromPyPDF2impo......
  • 大文件切片上传和断点续传
    大文件分片上传前端知识点md5加密算法用于确保信息传输完整一致sparkmd5在散列大量数据(例如文件)时表现得更好。可以使用FileReader和Blob读取块中的文件,并将每个块附加到md5//创建一个sparkmd5计算arrayBuffer的对象spark=newSparkMD5.ArrayBuffer()//添加到arrayb......