Servlet的文件上传下载

news2025/2/6 17:06:45

Servlet的文件上传|下载

二、文件上传实现

2.1实现思路
  1. 需要使用到Commons-FileUpload组件
  2. 需要将jsp页面form表单的enctype属性值设置为“multipart/form-data”,
  3. Servlet中使用IO流实现文件的上传
2.2、实现过程
2.2.1新建web项目导入jar包
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
2.2.2、编写页面

在webapp下编写upload.jsp页面,用于提供文件上传的form表单,需要注意的是,form表单的enctype属性值要设置为“multipart/form-data”,method属性值要设置为“post”,并将action属性值设置为“upServlet”

<!--
    文件上传
    1.准备表单
    2.设置表单的提交类型 method = "post"
    3.设置表单类型为文件上传表单 enctype=“multipart/form-data”
    4.设置文件提交的地址
    5.准备表单元素
        1.普通的表单项 type="text
        2.文件项 type="file"
    6.设置表单元素的name属性值(表单提交一定要设置表元素的name属性值,否则后台无法接收数据!)
 -->
<form action="upServlet" method="post"
      enctype="multipart/form-data">
    <table width="600px">
        <tr>
            <td>上传者</td>
            <td><input type="text" name="name" /></td>
        </tr>
        <tr>
            <td>上传文件</td>
            <td><input type="file" name="myfile"></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="上传" /></td>
        </tr>
    </table>
</form>

在这里插入图片描述

2.2.3、创建Servlet

在web项目的java文件夹下创建包com.kdf.upload,在该包中新建一个名称为UploadServlet的类,用于获取表单及其上传文件的信息。

package com.kdf.upload;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
//上传文件的Servlet类
@WebServlet(name = "UploadServlet",urlPatterns = "/upServlet")
//该注解用于标注文件上传的Servlet
@MultipartConfig
public class UploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)throws ServletException, IOException {
        try {
            //设置ContentType字段值
            response.setContentType("text/html;charset=utf-8");
            // 创建DiskFileItemFactory工厂对象
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //设置文件缓存目录,如果该目录不存在则新创建一个
            File f = new File("E:\\TempFolder");
            if (!f.exists()) {
                f.mkdirs();
            }
            // 设置文件的缓存路径
            factory.setRepository(f);
            // 创建 ServletFileUpload对象
            ServletFileUpload fileupload = new ServletFileUpload(factory);
            //设置字符编码
            fileupload.setHeaderEncoding("utf-8");
            // 解析 request,得到上传文件的FileItem对象
            List<FileItem> fileitems = fileupload.parseRequest(request);
            //获取字符流
            PrintWriter writer = response.getWriter();
            // 遍历集合
            for (FileItem fileitem : fileitems) {
                // 判断是否为普通字段
                if (fileitem.isFormField()) {
                    // 获得字段名和字段值
                    String name = fileitem.getFieldName();
                    if(name.equals("name")){
                        //如果文件不为空,将其保存在value中
                        if(!fileitem.getString().equals("")){
                            String value = fileitem.getString("utf-8");
                            writer.print("上传者:" + value + "<br />");
                        }
                    }
                } else {
                    // 获取上传的文件名
                    String filename = fileitem.getName();
                    //处理上传文件
                    if(filename != null && !filename.equals("")){
                        writer.print("上传的文件名称是:" + filename + "<br />");
                        // 截取出文件名
                        filename = filename.substring(filename.lastIndexOf("\\") + 1);
                        // 文件名需要唯一
                        filename = UUID.randomUUID().toString() + "_" + filename;
                        // 在服务器创建同名文件
                        String webPath = "/upload/";
                        //将服务器中文件夹路径与文件名组合成完整的服务器端路径
                        String filepath = getServletContext()
                                .getRealPath(webPath + filename);
                        // 创建文件
                        File file = new File(filepath);
                        file.getParentFile().mkdirs();
                        file.createNewFile();
                        // 获得上传文件流
                        InputStream in = fileitem.getInputStream();
                        // 使用FileOutputStream打开服务器端的上传文件
                        FileOutputStream out = new FileOutputStream(file);
                        // 流的拷贝
                        byte[] buffer = new byte[1024];//每次读取1个字节
                        int len;
                        //开始读取上传文件的字节,并将其输出到服务端的上传文件输出流中
                        while ((len = in.read(buffer)) > 0)
                            out.write(buffer, 0, len);
                        // 关闭流
                        in.close();
                        out.close();
                        // 删除临时文件
                        fileitem.delete();
                        writer.print("上传文件成功!<br />");
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        doGet(request, response);
    }
}

启动项目,选择文件进行上传。

在这里插入图片描述

在这里插入图片描述

三、文件下载

3.1download.jsp
<a href=
           "http://localhost:8080/DownloadServlet?filename=1.png">
    文件下载</a>
</body>
3.2servlet
package com.kdf.upload;
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
@WebServlet(name = "DownloadServlet",urlPatterns = "/DownloadServlet")
public class DownloadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public void doGet(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        //设置ContentType字段值
        response.setContentType("text/html;charset=utf-8");
        //获取所要下载的文件名称
        String filename = request.getParameter("filename");
        //下载文件所在目录
        String folder = "/download/";
        // 通知浏览器以下载的方式打开
        response.addHeader("Content-Type", "application/octet-stream");
        response.addHeader("Content-Disposition",
                "attachment;filename="+filename);
        folder=folder+filename;
        // 通过文件流读取文件
        InputStream in = getServletContext().getResourceAsStream(folder);
        // 获取response对象的输出流
        OutputStream out = response.getOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        //循环取出流中的数据
        while ((len = in.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        doGet(request, response);
    }
}

在这里插入图片描述

一、文件上传原理

要实现Web开发中的文件上传功能,通常需完成两步操作:

一是在Web项目的页面中添加上传输入项

二是在Servlet中读取上传文件的数据,并保存到目标路径中。
由于大多数文件的上传都是通过表单的形式提交给服务器的,因此,要想在程序中实现文件上传功能,首先要创建一个用于提交上传文件的表单页面。在表单页面中,需要使用标签在jsp页面中添加文件上传输入项。

1.1、文件域

标签的使用。

  • 必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据。
  • 必须把将表单页面的method属性设置为post方式,enctype属性设置为“multipart/form-data”类型。
<%--指定表单数据的enctype属性以及提交方式--%>
<form enctype="multipart/form-data" method="post">
	<%--指定标记的类型和文件域的名称--%>
	选择上传文件:<input type="file" name="myfile"/><br />
</form>

1.2、commons-fileUpload

当浏览器通过表单提交上传文件时,文件数据都附带在HTTP请求消息体中,并且采用MIME类型(多用途互联网邮件扩展类型)进行描述,在后台可以使用request对象提供的getInputStream()方法读取客户端提交过来的数据。

但由于用户可能会同时上传多个文件,而在Servlet端直接读取上传数据,并分别解析出相应的文件数据是一项非常麻烦的工作。为了方便处理用户上传的数据,Apache组织提供了一个开源组件Commons- FileUpload,该组件可以方便地将“multipart/form-data”类型请求中的各种表单域解析出来,并实现一个或多个文件的上传,文件上传的原理如下图所示。
在这里插入图片描述

1.3、FileItem接口

FileItem接口主要用于封装单个表单字段元素的数据,一个表单字段元素对应一个FileItem对象。Commons-FileUpload组件在处理文件上传的过程中,将每一个表单域(包括普通的文本表单域和文件域)封装在一个FileItem对象中。常用方法如下表所示:

方法声明功能描述
boolean isFormField()isFormField()方法用于判断FileItem类对象封装的数据是一个普通文本表单字段,还是一个文件表单字段,如果是普通文本表单字段则返回true,否则返回false。
String getName()getName()方法用于获取文件上传字段中的文件名。如果FileItem类对象对应的是普通文本表单字段,getName()方法将返回null,否则,只要浏览器将文件的字段信息传递给服务器,getName()方法就会返回一个字符串类型的结果,如C:\Sunset.jpg。
String getFieldName()getFieldName()方法用于获取表单字段元素描述头的name属性值,也是表单标签name属性的值。例如“name=file1”中的“file1”。
void write(File file)write()方法用于将FileItem对象中保存的主体内容保存到某个指定的文件中。如果FileItem对象中的主体内容是保存在某个临时文件中,那么该方法顺利完成后,临时文件有可能会被清除。另外,该方法也可将普通表单字段内容写入到一个文件中,但它主要用于将上传的文件内容保存到本地文件系统中。
String getString()getString()方法用于将FileItem对象中保存的数据流内容以一个字符串形式返回。它有两个重载的定义形式:①public String getString()②public String getString(java.lang.String encoding)前者使用默认的字符集编码将主体内容转换成字符串,后者使用参数指定的字符集编码将主体内容转换成字符串。
String getContentType()getContentType()方法用于获得上传文件的类型,即表单字段元素描述头属性“Content-Type”的值,如“image/jpeg”。如果FileItem类对象对应的是普通表单字段,该方法将返回null。
1.4、DiskFileItemFactory类

DiskFileItemFactory类用于将请求消息实体中的每一个文件封装成单独的FileItem对象。如果上传的文件比较小,将直接保存在内存中,如果上传的文件比较大,则会以临时文件的形式,保存在磁盘的临时文件夹中。默认情况下,不管文件保存在内存还是磁盘临时文件夹,文件存储的临界值是10240字节,即10KB。

方法声明功能描述
DiskFileItemFactory()采用默认临界值和系统临时文件夹构造文件项工厂对象
DiskFileItemFactory(int sizeThreshold,File repository)采用参数指定临界值和系统临时文件夹构造文件项工厂对象

DiskFileItemFactory(int sizeThreshold,File repository)构造方法传递两个参数,第一个参数sizeThreshold表示文件保存在内存还是磁盘临时文件夹中的临界值,第二个参数repository表示临时文件的存储路径。

1.5、ServletFileUpload类

ServletFileUpload类是Apache组件处理文件上传的核心高级类,通过调用parseRequest(HttpServletRequest) 方法可以将HTML中每个表单提交的数据封装成一个FileItem对象,然后以List列表的形式返回。

方法声明功能描述
ServletFileUpload()构造一个未初始化的ServletFileUpload实例对象
ServletFileUpload(FileItemFactory fileItemFactory)根据参数指定的FileItemFactory 对象创建一个ServletFileUpload对象

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

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

相关文章

NLP的奥秘:用 Python 揭秘人类语言与人工智能的桥梁【6000 字长文含代码示例】

目录 NLP 的核心任务 NLP 的发展历史 NLP 的技术与方法 传统的 NLP 技术与方法 规则基础方法&#xff1a;语言学的智慧 统计学习方法&#xff1a;数据的力量 深度学习方法&#xff1a;人工智能的新浪潮 NLP 的应用领域 Python在 NLP 中的应用 1、NLTK (Natural Langu…

数字孪生与企业

数字孪生技术&#xff0c;简而言之&#xff0c;就是创造一个物理实体的数字双胞胎&#xff0c;在虚拟世界中精确模拟现实世界的行为、过程和系统。这种技术的核心在于&#xff0c;它允许我们在数字环境中实时地监控、分析和优化其物理对应物的性能和效率。数字孪生的应用场景极…

node.js服务器静态资源处理

前言&#xff1a;node.js服务器动态资源处理见 http://t.csdnimg.cn/9D8WN 一、什么是node.js服务器静态资源&#xff1f; 静态资源服务器指的是不会被服务器的动态运行所改变或者生成的文件. 它最初在服务器运行之前是什么样子, 到服务器结束运行时, 它还是那个样子. 比如平…

基于springboot+vue+Mysql的校园新闻网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

HarmonyOS实战开发-如何实现电话服务中发送短信的功能。

介绍 本示例使用ohos.telephony.sms 接口展示了电话服务中发送短信的功能。 效果预览 使用说明&#xff1a; 首页点击创建联系人&#xff0c;弹框输入联系人姓名和电话&#xff0c;点击确定按钮后&#xff0c;联系人列表中添加该联系人;点击管理&#xff0c;该按钮变成取消&…

[数据结构]——二叉树——堆的实现

1. 堆的概念及结构 如果有一个关键码的集合K { &#xff0c; &#xff0c; &#xff0c;…&#xff0c; }&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储 在一个一维数组中&#xff0c;并满足&#xff1a; < 且 < ( > 且 > ) i 0&#xff0c;1&…

如何使用OSI七层模型的思路进行Linux网络问题排障?

在运维工作中&#xff0c;我们可能经常遇到诸如服务器无法远程连接、网站无法访问等各种网络问题。此时你是否想过&#xff0c;我们常背的OSI七层模型&#xff0c;能在处理这样的实际问题中发挥什么样的作用呢&#xff1f; 基于OSI架构的方法论&#xff0c;我们可以使用自下而…

OpenHarmony轻量系统开发【5】驱动之GPIO点灯

5.1点灯例程源码 先看最简单得LED灯闪烁操作 源码结构如下&#xff1a; 第一个BUILD.gn文件内容&#xff1a; static_library("led_demo") {sources ["led_demo.c"]include_dirs ["//utils/native/lite/include","//kernel/liteos_m/c…

FL Studio v21.2.3.4004 中文永久版网盘下载(含Key.reg注册表补丁)

软件介绍 FL Studio21水果编曲软件汉化版是一款专业的音乐制作软件&#xff0c;被广泛地应用于电子音乐、hip-hop、流行乐等多种音乐类型的制作。该软件提供了丰富的音频编曲工具和音乐效果器&#xff0c;让用户可以轻松地创作出高品质的音乐作品。同时&#xff0c;这也是一款…

配置优先级标记和队列调度示例

配置优先级标记和队列调度示例 组网图形 图1 优先级标记和队列调度示例组网图 优先级标记和队列调度简介配置注意事项组网需求配置思路操作步骤配置文件 优先级标记和队列调度简介 报文进入设备之后&#xff0c;设备会根据相应的规则分配或修改报文各种优先级的值&#xff…

Spring 事务失效总结

前言 在使用spring过程中事务是被经常用的&#xff0c;如果不小心或者认识不做&#xff0c;事务可能会失效。下面列举几条 业务代码没有被Spring 容器管理 看下面图片类没有Componet 或者Service 注解。 方法不是public的 Transactional 注解只能用户public上&#xff0c…

51单片机入门_江协科技_29~30_OB记录的自学笔记_DS18B20温度传感器

29. DS18B20温度传感器 29.1. DS18B20介绍 •DS18B20是一种常见的数字温度传感器&#xff0c;其控制命令和数据都是以数字信号的方式输入输出&#xff0c;相比较于模拟温度传感器&#xff0c;具有功能强大、硬件简单、易扩展、抗干扰性强等特点 •测温范围&#xff1a;-55C 到 …

k8s的service为什么不能ping通?——所有的service都不能ping通吗

点击阅读原文 前提&#xff1a;kube-proxy使用iptables模式 Q service能不能ping通&#xff1f; A: 不能&#xff0c;因为k8s的service禁止了icmp协议 B: 不能&#xff0c;因为clusterIP是一个虚拟IP&#xff0c;只是用于配置netfilter规则&#xff0c;不会实际绑定设备&…

腾讯EdgeOne产品测评体验—Web服务全能一体化服务,主打一步到位

前言 现在网络Web攻击真的防不胜防啊&#xff0c;相信有很多独狼开发者自己建站&#xff0c;租个云服务器&#xff0c;一部署自己的服务&#xff0c;每隔一段时间内测和网站总有一个要崩。自己感觉难受不说&#xff0c;网站稍微有点要出头的时候&#xff0c;数不清的访问攻击就…

汽车车灯用肖特基二极管,选什么型号好?

肖特基二极管种类繁多&#xff0c;有低压降肖特基二极管、通用型肖特基二极管、快速恢复型肖特基二极管、高功率肖特基二极管、汽车级肖特基二极管等等&#xff0c;其中低压降肖特基二极管和汽车级肖特基二极管是二极管厂家东沃电子的核心优势产品。关于东沃电子推出的低压降肖…

FFmpeg: 自实现ijkplayer播放器--05ijkplayer–连接UI界面和ffplay.c

文章目录 ijkplayer时序图消息循环--回调函数实现播放器播放时状态转换播放停止ijkmediaPlay成员变量成员函数ijkplayer时序图 stream_open: frame_queue_init packet_queue_init init_clock 创建read_thread线程 创建video_refresh_thread线程 消息循环–回调函数实现 ui 和…

Spectral Adversarial MixUp for Few-Shot Unsupervised Domain Adaptation论文速读

文章目录 Spectral Adversarial MixUp for Few-Shot Unsupervised Domain Adaptation摘要方法Domain-Distance-Modulated Spectral Sensitivity (DoDiSS&#xff09;模块Sensitivity-Guided Spectral Adversarial Mixup (SAMix)模块 实验结果 Spectral Adversarial MixUp for F…

在线教程|低门槛部署!SUPIR 专治各种图片模糊,还能理解文本描述进行精修

家庭相册中泛黄的老照片&#xff0c;历史档案中尘封的影像资料&#xff0c;科研实验中沉淀下的图片资源…… 图像作为一种重要的信息载体&#xff0c;不仅承载了消逝的时光与故事&#xff0c;也记录着人类对历史的探索和传承。然而&#xff0c;由于早期保存条件的限制&#xf…

Go 编译构建的一些细节

Go 编译构建的一些细节 发现自己竟然没有怎么认真研究过 go 的编译构建命令。 结论前置 go run 专门用来运行命令源码文件的命令&#xff0c;一般用来运行单个文件go build 主要是用于测试编译。编译某个包或者项目&#xff0c;在当前目录下生成可执行文件go install 编译并…

(4)步态识别论文研读——用于步态识别的分层时空表示学习

论文题目Hierarchical Spatio-Temporal Representation Learning for Gait Recognition 论文地址 https://arxiv.org/abs/2307.09856 1.摘要 步态识别是一种生物特征技术&#xff0c;通过其独特的行走方式识别个体&#xff0c;适用于无约束环境&#xff0c;具有广泛的应用。…