JavaWeb之文件的上传和下载

news2024/11/18 17:47:37

文章目录

    • 文件的上传
      • 基本介绍
      • 文件上传的HTTP协议的说明
      • commons-fileupload.jar 常用API介绍说明
      • fileupload类库的使用
    • 文件的下载
      • 基本介绍和使用说明
      • 中文名乱码问题解决方案

文件的上传和下载,是非常常见的功能。很多的系统中,或者软件中都经常使用文件的上传和下载。
比如:QQ 头像,就使用了上传。 邮箱中也有附件的上传和下载功能。 OA 系统中审批有附件材料的上传

文件的上传

基本介绍

:::tips
基本操作:

  1. 要有一个form标签,method=post请求
  2. form标签的encType属性值必须为multipart/form-data值
  3. 在form标签中使用 input type=file 添加上传的文件
  4. 编写服务器代码(Servlet程序)接受,处理上传的数据

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

文件上传的HTTP协议的说明

image.png
image.png

  • 下面上传的文件的数据其实是没有显示出来,是存在的,只是浏览器认为你的数据很多,然后认为显示出来不好看,于是就没有显示出来,在IDEA的界面上是可以显示出来的

注意:客户端以流的形式来接受
image.png

commons-fileupload.jar 常用API介绍说明

  • 对于文件上传的方式,有很多第三方类已经很好的完成了
  • 这里我们使用comms-fileupload-jar包,而由于这个jar包依赖commons-io.jar包,所以我们需要引入两个包

image.png

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

fileupload类库的使用

  • 上传文件的表单:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
    <form action="http://localhost:8080/09_EL_JSTL/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>
  • 解析上传的数据的代码:
package com.zan.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.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 {
    /**
    *
    * @param req
    * @param resp
    * @throws ServletException
    * @throws IOException
    */
    @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 {
                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());
                    	//将文件写入磁盘位置
                        fileItem.write(new File("e:\\" + fileItem.getName()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

image.png

文件的下载

基本介绍和使用说明

:::tips
下载的常用API说明:
**response.getOutputStream();//**获取响应的输出流
servletContext.getResourceAsStream();
**servletContext.getMimeType();//**获取要下载的文件类型
**response.setContentType();//**通过响应头告诉客户端返回的数据类型
:::
:::tips
response.setHeader(“Content-Disposition”, “attachment; fileName=1.jpg”);
这个响应头告诉浏览器,这是需要下载的,而attachment表示附件,也就是下载的一个文件,fileName=后面表示下载的文件名
:::

package com.zan.servlet;

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

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

public class Download extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取要下载的文件名
        String downloadFileName = "0.jpg";//固定一下
        //2. 读取要下载的文件内容(通过ServletContext对象可以读取)
        ServletContext servletContext = getServletContext();
        //获取要下载的文件类型
        String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
//        System.out.println(mimeType);
        //4. 在回传前,通过响应头告诉客户端返回的数据类型
        resp.setContentType(mimeType);
        //5. 还要告诉客户端收到的数据是用于下载使用(还是使用响应头来告诉)
        //Content-Disposition 响应头,表示收到的数据怎么处理
        //attachment 表示附件,表示下载使用
        //filename= 表示指定下载的文件名
        //url 编码是把汉字转换成为%xx%xx的格式,xx就是十六进制
        if (req.getHeader("User-Agent").contains("Firefox")) {
            //如果是火狐浏览器使用Base64编码
            resp.setHeader("Content-Disposition", "attachment; filename==?charset?B?" + new BASE64Encoder().encode("中国.jpg".getBytes()) + "?=");
        } else {
            //如果不是火狐,是IE或谷歌,使用URL编码操作
            resp.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("中国.jpg", "UTF-8"));
        }
        /**
         * 斜杠 /  被服务器解析表示地址为http://ip:port/工程名/  映射到代码的web目录
         */
        InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
        //获取响应的输出流
        OutputStream outputStream = resp.getOutputStream();
        //3. 把下载的文件内容回传给客户端
        //读取输入,将输入流的内容复制给输出流,输出给客户端
        IOUtils.copy(resourceAsStream, outputStream);
    }
}

image.png

中文名乱码问题解决方案

  • URLEncoder解决IE和谷歌浏览器的附件中文名问题
    :::tips
    如果客户端浏览器是 IE 浏览器 或者 是谷歌浏览器。我们需要使用 URLEncoder 类先对中文名进行 UTF-8 的编码操作
    因为 IE 浏览器和谷歌浏览器收到含有编码后的字符串后会以 UTF-8 字符集进行解码显示
    :::
// 把中文名进行 UTF-8 编码操作。
String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8");
// 然后把编码后的字符串设置到响应头中
response.setHeader("Content-Disposition", str);

image.png

  • BASE64编解码解决火狐浏览器的附件中文名问题
    :::tips
    如果客户端浏览器是火狐浏览器。 那么我们需要对中文名进行 BASE64 的编码操作。
    这时候需要把请求头 Content-Disposition: attachment; filename=中文名
    编码成为:Content-Disposition: attachment; filename==?charset?B?xxxxx?=
    :::
    | **=? ** | **表示编码内容的开始 ** |
    | — | — |
    | **charset ** | **表示字符集 ** |
    | **B ** | 表示 BASE64 编码 |
    | xxxx | ** 表示文件名 BASE64 编码后的内容 ** |
    | **?= ** | 表示编码内容的结束 |

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/670192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用spacy做分词的示例

下载数据&#xff1a; aws s3 cp s3://applied-nlp-book/data/ data --recursive --no-sign-request aws s3 cp s3://applied-nlp-book/models/ag_dataset/ models/ag_dataset --recursive --no-sign-request 上面第一份数据接近1GB&#xff0c;第二份接近3GB&#xff1b; 示…

买了一年CSDN年VIP,用着实在太爽

买一年CSDN的年VIP有多爽及使用攻略&#xff01; 一、前言 这段时间&#xff0c;一旦打开CSDN就不断的弹出618活动&#xff0c;在电脑网上打开&#xff0c;一股白嫖之的气息吹来&#xff0c;让人直接忍不住剁手 最后经过近5天的挣扎&#xff0c;我还是受不了CSDN的蛊惑&#…

【工具分享】批量多目录图片如何转换PDF,一次性转换多级目录批量的PDF的转换,合并,输出另存等问题

在工作中我们经常要对图片进行批量转换PDF&#xff0c;由于文件量比较多&#xff0c;目录比较深&#xff0c;工作量比较大比较耗时费力&#xff0c;今天我们分享的主要解决以下问题&#xff1a; 1、单张图片的转换PDF&#xff1a;一张图临时转一下 2、多张图片转换成PDF&…

(二叉树) 1382. 将二叉搜索树变平衡 ——【Leetcode每日一题】

❓1382. 将二叉搜索树变平衡 难度&#xff1a;中等 给你一棵二叉搜索树&#xff0c;请你返回一棵 平衡后 的二叉搜索树&#xff0c;新生成的树应该与原来的树有着相同的节点值。如果有多种构造方法&#xff0c;请你返回任意一种。 如果一棵二叉搜索树中&#xff0c;每个节点…

whistle 使用介绍

什么是 whistle 来自 whistle 官网&#xff1a;http://wproxy.org/whistle/ 的介绍&#xff1a; whistle(读音[ˈwɪsəl]&#xff0c;拼音[wēisǒu])基于Node实现的跨平台web调试代理工具&#xff0c;类似的工具有Windows平台上的Fiddler&#xff0c;主要用于查看、修改HTTP…

在 Python 中对日期和时间进行排序

文章目录 在 Python 中对日期和时间进行排序Python 中的日期时间模块sorted() 方法 使用 sorted() 方法对日期进行排序使用 sorted() 方法对时间进行排序使用 sorted() 方法对日期和时间进行排序总结 Python 是全世界程序员都在使用的一种高级解释型编程语言。 它最著名的是面向…

C++指针对象和异常(10)

异常(exception) 为什么有异常 异常在C用于错误处理&#xff0c;C语言中一般使用返回值表示错误&#xff0c;C对错误处理进行了扩展&#xff0c;统一使用异常机制来处理程序中发生的错误。 C的异常处理包括两个部分 ----- 抛出异常和捕获异常&#xff0c;如果抛出的异常被捕…

BW生成HANA视图权限配置

目录 1 操作步骤1.1 SAP HANA端1、创建用户2、常规信息3、配置角色4、配置系统权限5、配置对象权限 1.2 BW端1、SM30配置数据库连接参数2、SU01创建账户&#xff08;与SAP HANA数据库账户名一致&#xff09;3、使用RS2HANA_VIEW查看配置Assignment TypeDB Connection NameLimit…

如何解决亚马逊、ebay砍单、封号问题?稳定测评方案分析

很多卖家和工作室朋友询问我为什么在测评过程中经常遇到砍单和封号的问题。实际上&#xff0c;这并不难理解&#xff0c;因为测评所涉及的技术问题很多&#xff0c;并不能仅通过解决IP或环境的单一因素来实现稳定的测评。 目前市面上存在许多技术方案&#xff0c;例如指纹浏览…

火山引擎Dataleap治理实践:如何降低数仓建设成本

背景 存储与计算资源是数仓建设的基础&#xff0c;也是数仓建设中的重要成本支出。而随着数仓建设规模逐渐扩大、时间跨度逐渐拉长&#xff0c;将不可避免的出现数据表、任务、字段的冗余。为了减轻资源负担&#xff0c;降低数仓维护成本&#xff0c;需要对数仓建设成本进行治…

微信小程序-上传代码失败,提示分包大小超过限制

开发者可通过开发者工具中的性能扫描工具提前发现代码中的可优化项&#xff1a; 1. 代码包不包含插件大小超过 1.5 M 【建议】小程序代码包单个包大小限制为2M。因此我们建议开发者在开发时&#xff0c;如果遇到单包体积大于1.5M的情况&#xff0c;可以采取分包的方式&#x…

Star History 月度开源精选|2023 年 5 月

收集完五月的 Star History 精选之后我们惊讶地发现居然有那么多好玩好用的项目&#xff0c;无论是低代码&#xff0c;或是可以帮你少写代码&#xff0c;即便不是专业开发者也可以上手了&#xff01; Windmill Windmill 可以看做是 Airplane 的开源替代品 / Temporal 的低代码…

安科瑞产品在泛在电力物联网的应用

安科瑞虞佳豪 泛在电力物联网是以通讯技术为基础发展而来的新型物联网体系&#xff0c;其构建的核心是满足电网能源系统的智能判断和自适应调节能力&#xff0c;这将提高能源的替代和利用能力。对于电力物联网来说&#xff0c;通讯技术是其核心的技术内容之一&#xff0c;也是…

直播平台中的美颜SDK技术探究

而在直播过程中&#xff0c;美颜技术的应用已经成为了不可或缺的一部分。美颜技术能够让主播在镜头前变得更加漂亮自信&#xff0c;也能够提高直播的观看体验。在直播平台中&#xff0c;美颜SDK技术的探究就显得尤为重要。 一、美颜SDK技术的定义 美颜SDK技术是一种通过算法…

Java中的增强 for 循环 foreach

foreach 是 Java 中的一种语法糖&#xff0c;几乎每一种语言都有一些这样的语法糖来方便程序员进行开发&#xff0c;编译期间以特定的字节码或特定的方式来对这些语法进行处理。能够提高性能&#xff0c;并减少代码出错的几率。在 Java 中还有比如 泛型、自动拆箱、自动装箱、内…

【集合数据类型详解】——基础语法

目录索引 集合特点&#xff1a;集合用处&#xff1a;去重操作&#xff1a; 创建集合&#xff1a;实例&#xff1a;实例2&#xff1a; 集合运算&#xff1a;交集&#xff1a;并集&#xff1a;补集&#xff1a;差集&#xff1a; 集合特点&#xff1a; 同一集合中&#xff0c;只能…

ssm酒店住宿预定系统-计算机毕设 附源码 87020

ssm酒店住宿预定系统 目 录 摘要 1 绪论 1.1 研究背景 1.2开发意义 1.3ssm框架 1.4论文结构与章节安排 2 2 酒店住宿预定系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3数据删除流程 2.3 系统功能分析 2.3.1功能性分…

使用Servlet完成单表的增删改查功能以及使用模板方法设计模式解决类爆炸问题(重写service模板方法)

使用Servlet做一个单表的CRUD操作 开发前的准备 导入sql脚本创建一张部门表 drop table if exists dept; create table dept(deptno int primary key,dname varchar(255),loc varchar(255) ); insert into dept(deptno, dname, loc) values(10, XiaoShouBu, BeiJing); inser…

【读书笔记】《认知觉醒》- 周岭

不停的阅读&#xff0c;然后形成自己的知识体系。 2023.06.25 读 文章目录 自序 开启自我改变的原动力上篇 内观自己&#xff0c;摆脱焦虑第一章 大脑——一切问题的起源第一节 大脑&#xff1a;重新认识你自己三重大脑高低之分与权力之争成长就是克服天性的过程 自序 开启自我…

深度学习训练过程耗时越来越长解决方法

自己的情况是代码中有过多的图片显示&#xff0c;导致每个iteration/epoch训练时间越来越长。或其他类似的东西。 解决方法&#xff1a; 用plt.close()及时关闭图片 fig plt.figure(0) # 新图0 plt.savefig( ) # 保存 plt.close(0) # 关闭图0plt.close(all) #关闭所有图…