JavaWeb 文件上传和下载

目录

一、文件上传

        1.文件上传和下载的使用说明 : 

        2.文件上传基本原理 : 

        3.文件上传经典案例 : 

            3.1 页面实现: 

            3.2 servlet实现 : 

            3.3 工具类实现 : 

            3.4 运行测试 : 

            3.5 注意事项 : 

二、文件下载

        1.文件下载基本原理 : 

        2.文件下载经典案例 : 

            2.1 准备工作

            2.2 页面实现 

            2.3 servlet实现

            2.4 运行测试 

            2.5 注意事项


一、文件上传

        1.文件上传和下载的使用说明 : 

        web文件上传和下载需要用到三个jar包(fileupload2版本, tomcat10),如下图所示 : 

        2.文件上传基本原理 : 

        客户端——

        (1) 使用表单提交数据

        (2) 表单属性action仍然指向目标web资源(数据提交给该web资源)

        (3) 表单属性method指定为post

        (4) 表单属性enctype,指encodetype,编码类型;默认为application/x-www-form-urlencoded,即url编码,这种编码不适合二进制文件数据的提交,一般是适用于文本数据。若想进行二进制文件的提交,需要指定enctype为multipart/form-data,表示表单提交的数据是由多个部分组成,也就是可以提交二进制数据和文本数据。

        服务端——

        (1) 判断是否为一个文件表单;

        (2) 判断文件表单所提交的各个表单项分别是什么类型;

        (3) 如果是一个普通文本表单项,就按照文本的方式来处理;如果是一个文件表单项(二进制数据) ,就使用IO技术进行处理

        (4) 把表单提交的文件数据,保存到指定的服务端的某个目录。

        3.文件上传经典案例 : 

            3.1 页面实现: 

                页面效果如下 : 

                upload.jsp代码如下 : 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><base href="<%=request.getContextPath()+"/"%>>"><style type="text/css">table, td {border:2px pink dashed;border-collapse: collapse;padding: 5px}img {border-radius: 50%;}input[type="file"] {position: absolute;left: 0;top: 0;height: 200px;opacity: 0;cursor: pointer}input[type="submit"] {width: 150px}#td01 {width: 100px;text-align: center}</style><script type="text/javascript">function prev(event) {//获取展示图片的区域var img = document.getElementById("prevView");//获取文件对象var file = event.files[0];//获取文件阅读器(JS的一个类FileReader)var reader = new FileReader();reader.readAsDataURL(file);reader.onload = function () {//给img的src设置图片urlimg.setAttribute("src", this.result);}}</script></head>
<body>
<!--form表单属性的注意事项 :(1) action : 注意此页面中base标签的指定(2) enctype="multipart/form-data", 表示提交的数据是多个部分构造,有文件和文本-->
<form action="fileUploadServlet" method="post" enctype="multipart/form-data"><table width="350px"><tr><td>上传的图片:</td><td><img src="2.jpg" alt="" width="200" height="200" id="prevView"><input type="file" name="pic" id="" value="" onchange="prev(this)"/></td></tr><tr><td>文件名(self-def):</td><td><input type="text" name="name"><br/></td></tr><tr><td colspan="2" id="td01"><input type="submit" value="Submit"/></td></tr></table>
</form>
</body>
</html>

            3.2 servlet实现 : 

                定义一个servlet来实现文件上传的功能,需要用到导入的jar包的工具类。FileUploadServlet类代码如下 : 

package servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload2.core.DiskFileItem;
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
import org.apache.commons.fileupload2.jakarta.JakartaServletFileUpload;
import utils.WebUtils;import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;/*** @author : Cyan_RA9* @version : 21.0*/
@WebServlet(urlPatterns = {"/fileUploadServlet"})
public class FileUploadServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) {//1.判断是否为一个文件表单if (JakartaServletFileUpload.isMultipartContent(req)) {//2.创建一个DiskFileItemFactory对象(注意创建方式同低版本不同)DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory.Builder().get();//3.利用得到的diskFileItemFactory对象,创建一个解析上传数据的工具对象JakartaServletFileUpload<DiskFileItem, DiskFileItemFactory> jakartaServletFileUpload =new JakartaServletFileUpload<>(diskFileItemFactory);jakartaServletFileUpload.setHeaderCharset(StandardCharsets.UTF_8);  //乱码问题//4.利用工具对象,将表单提交的数据(text or file) 封装到DiskFileItem中try {List<DiskFileItem> diskFileItems = jakartaServletFileUpload.parseRequest(req);//5.遍历获取到的集合for (DiskFileItem diskFileItem : diskFileItems) {//6.判断是否为文件类型(true表示不是文件,是input type=text)if (diskFileItem.isFormField()) {String name = diskFileItem.getString(StandardCharsets.UTF_8);System.out.println("文件名(self-def) = " + name);} else {    //false表示是文件//7.如果判断为是文件,就将上传的文件保存到本地。String filePath = "/upload/";//通过ServletContext对象,得到真实的工作路径String realPath = req.getServletContext().getRealPath(filePath);System.out.println("realPath = " + realPath);String fileName = diskFileItem.getName();System.out.println("fileName = " + fileName);//8.由于实际工作的路径与web路径不同,所以需要创建目录//利用定义的工具类,创建分级目录,提高程序执行的效率。String finalPath = realPath + WebUtils.getLocalDate();File file = new File(finalPath);if (!file.exists()) {file.mkdirs();}//9.将上传的文件拷贝到服务端的指定目录/*(1) 注意得到Path的两种方式(2) 解决文件重名问题,给文件名加一个前缀,保证是唯一即可。*/fileName = UUID.randomUUID().toString() + "_" + fileName;diskFileItem.write(new File(finalPath + fileName).toPath());}}} catch (IOException e) {throw new RuntimeException(e);}} else {System.out.println("不是一个表单捏~");}}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}
}

            3.3 工具类实现 : 

                定义一个工具类,用来对文件名作标识,以解决文件重名导致的文件覆盖问题。
                WebUtils类代码如下 : 

package utils;import java.time.LocalDateTime;/**@function : 该方法返回一个日期形式的字符串路径*/
public class WebUtils {public static String getLocalDate() {LocalDateTime ldt = LocalDateTime.now();int year = ldt.getYear();int month = ldt.getMonthValue();   //获取月份的值int dayOfMonth = ldt.getDayOfMonth();String localDate = year + "/" + month + "/" + dayOfMonth + "/";return localDate;}
}

            3.4 运行测试 : 

                测试结果如下GIF : 

            3.5 注意事项 : 

        (1) 同一个目录下上传了很多文件时,会造成访问文件速度变慢的问题,因此可以将文件上传到不同的目录,例如按照上传日期进行分类, eg : 2023/9/2/。

        (2) 一次完美的文件上传需要考虑很多因素,eg : 断点续传,对图片大小和尺寸的限制,分片上传,防止恶意上传等。PS : 在项目中,可以考虑百度开发的WebUploader组件。

        (3) 文件上传功能在项目中应该有限制的使用,一般用在头像、证明、合同、产品展示等;如果不加限制,会造成服务器空间被大量占用(eg : 微信朋友圈最多一次发9张)。

        (4) Tomcat在启动时,不会为web目录下的空文件夹在out目录下创建对应的文件夹,所以,需要在空文件夹中事先放入一个文件。


二、文件下载

        1.文件下载基本原理 : 

        服务器端要设置两个重要的HTTP响应头——

        (1) Content-Disposition : 表示下载数据的展示方式,比如是内联形式(即网页形式或者网页的一部分),或者是文件下载方式(attachment)。
        (2) Content-Type : 指定返回数据的MIME类型。        

        而响应体,在网络传输时是图片的原生数据(即按照浏览器下载的编码),而下载后查看到的是浏览器本身解析后的文件

        2.文件下载经典案例 : 

            2.1 准备工作

                将要下载的文件拷贝到web目录的sources目录下,如下图所示 : 

            2.2 页面实现 

                页面效果如下 : 

                download.jsp代码如下 : 

<%--User : Cyan_RA9Version : 21.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><meta charset="UTF-8"/><title>Title</title><base href="<%= request.getContextPath() + "/"%>"/>
</head>
<body>
<h1>文件下载</h1>
<a href="fileDownloadServlet?name=miku_flowers.jpg">点我下载初音未来</a> <br/><br/>
<a href="fileDownloadServlet?name=3.txt">点我下载王勃的滕王阁诗</a>
</body>
</html>

            2.3 servlet实现

                定义一个servlet,完成文件下载的功能。
                FileDownloadServlet代码如下 : 

package servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;/*** @author : Cyan_RA9* @version : 21.0*/
@WebServlet(urlPatterns={"/fileDownloadServlet"})
public class FileDownloadServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1.得到文件名和文件路径(文件资源的路径!)req.setCharacterEncoding("utf-8");String fileName = req.getParameter("name");String filePath = "/sources/" + fileName;//2.通过ServletContext对象得到文件的MIME类型String mimeType = req.getServletContext().getMimeType(filePath);System.out.println("mimeType = " + mimeType);//3.设置第一个响应头Content-Typeresp.setContentType(mimeType);//4.设置第一个响应头Content-Disposition//Content-Disposition用于指定下载的数据的展示形式,其中attachment表示使用文件下载方式//不同浏览器需要的编码格式不同if (req.getHeader("User-Agent").contains("Chrome")) {resp.setHeader("Content-Disposition", "attachment; filename=" +URLEncoder.encode(fileName, "UTF-8"));} else {//其他浏览器的编码操作}//5.读取文件,将读取到的文件返回给客户端(IO流拷贝的封装)//获取与数据源文件相关联的字节输入流InputStream resourceAsStream = req.getServletContext().getResourceAsStream(filePath);//获取与目的地文件相关联的字节输出流ServletOutputStream outputStream = resp.getOutputStream();//利用封装好的工具类,进行IO流拷贝IOUtils.copy(resourceAsStream, outputStream);}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req, resp);}
}

            2.4 运行测试 

                运行效果如下图所示(GIF图)

            2.5 注意事项

        (1) 不同的浏览器,对于下载的文件的处理方式不同,有些是直接打开该文件,有些则是将文件下载到本地的指定下载目录。

        (2) 对于网站上的文件,很多文件可以使用“另存为”来下载;对于大文件(文档,视频等),往往使用专业的下载工具(eg : 迅雷,百度网盘等)。

        (3) 注意,不同的浏览器对文件解码格式的需求不同。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于C语言参数传递的

一、C语言参数传递是整体带入 #include <stdio.h> #define DF(a,b) (a2*b) int main() { int s5; int k DF((s1),(s-3)); printf("%d",k); }输出结果 原因&#xff1a; #define DF(a,b) (a2*b) int k DF((s1),(s-3)); //等效 int k DF((s1)2 * (s-3)); …

useEffect 不可忽视的 cleanup 函数

在 react 开发中&#xff0c; useEffect 是我们经常会使用到的钩子&#xff0c;一个基础的例子如下&#xff1a; useEffect(() > {// some code here// cleanup 函数return () > {doSomething()} }, [dependencies])上述代码中&#xff0c; cleanup 函数的执行时机有如下…

代码随想录笔记--栈与队列篇

目录 1--用栈实现队列 2--用队列实现栈 3--有效的括号 4--删除字符串中的所有相邻重复项 5--逆波兰表达式求值 6--滑动窗口的最大值 7--前k个高频元素 1--用栈实现队列 利用两个栈&#xff0c;一个是输入栈&#xff0c;另一个是输出栈&#xff1b; #include <iostrea…

Windows 重新映射 CapsLock 大写锁定到 Ctrl

Windows 重新映射 CapsLock 大写锁定到 Ctrl 本要点中的这些方法适用于我的美国键盘布局。我不确定其他布局。如果出现问题&#xff0c;请恢复您的更改&#xff1b;删除您创建的注册表项&#xff08;并重新启动&#xff09;。 强烈推荐 方法5 ctrl2cap&#xff0c;因为不会影…

Modbus通信协议

Modbus通信协议 一、概述 Modbus通信协议是一种工业现场总线协议标准&#xff0c;常用的Modbus协议有以下三种类型&#xff1a;Modbus TCP、Modbus RTU、Modbus ASCll。 Modbus通信协议解决了通过串行线路在电子设备之间发送信息的问题。该协议在遵循该协议的体系结构中实现主…

Elasticsearch 7.6 - API高阶操作篇

ES 7.6 - API高阶操作篇 分片和副本索引别名添加别名查询所有别名删除别名使用别名代替索引操作代替插入代替查询 场景实操 滚动索引索引模板创建索引模板查看模板删除模板 场景实操一把索引的生命周期数据迁移APIGEO(地理)API索引准备矩形查询圆形查询多边形查询 自定义分词器…

小白学Go基础01-Go 语言的介绍

Go 语言对传统的面向对象开发进行了重新思考&#xff0c;并且提供了更高效的复用代码的手段。Go 语言还让用户能更高效地利用昂贵服务器上的所有核心&#xff0c;而且它编译大型项目的速度也很快。 用 Go 解决现代编程难题 Go 语言开发团队花了很长时间来解决当今软件开发人员…

ThinkPHP 文件上传 fileSystem 扩展的使用

ThinkPHP 文件上传 ThinkPHP 文件上传 扩展 filesystem一、安装 FileSystem 扩展二、认识 filesystem 配置文件 config/filesystem.php三、上传验证&#xff08;涉及到验证器的知识点&#xff09;四、文件上传demo ThinkPHP 文件上传 扩展 filesystem ThinkPHP 为我们 提供了 …

C语言每日一练---Day(14)

本专栏为c语言练习专栏&#xff0c;适合刚刚学完c语言的初学者。本专栏每天会不定时更新&#xff0c;通过每天练习&#xff0c;进一步对c语言的重难点知识进行更深入的学习。 今日练习题关键字&#xff1a;统计每个月兔子的总数 数列的和 &#x1f493;博主csdn个人主页&#x…

Stable Diffusion 多视图实践

此教程是基于秋叶的webui启动器 1.Stable Diffsuion 使用多视图需要准备一个多角度open pose 图 我给大家提供一个可使用的。 2.需要添加图片到到controlnet当中,不要选择预处理器,选择模型为openpose的模型,然后需要点选同步图片尺寸。 3.然后填写关键字可以参照一下这个…

zookeeper 理论合集

目录 系统背景 集群结构 多个节点之间的角色 节点的状态 为什么引入 Observer 存储结构 ZNode 节点结构 ZNode 创建类型 内存数据存储 数据持久化 zookeeper 的容量大小 数据同步 消息广播 崩溃恢复 如何保证顺序一致性 核心流程 Leader 选举流程 脑裂问题 …

【nginx】access.log按照时间分割

access.log 大的网络访问下没有几天文件就变得非常大了&#xff0c;一直累计也不是办法啊 查看文件大小 du -sh *access.log 13G 按照时间把access.log分割一下 修改 nginx.conf 修改前的文件 修改后的文件 增加的内容 map $time_iso8601 $logdate {~^(?<ymd>\d{4}…

【ArcGIS Pro二次开发】(65):进出平衡SHP转TXT、TXT转SHP

最近一个小伙伴提了这么一个需求&#xff0c;需要把TXT和SHP进行互转。 这种TXT文件其实遇到了好几个版本&#xff0c;都有一点小差异。之前已经做过一个TXT转SHP的工具&#xff0c;但好像不适用。于是针对这个版本&#xff0c;做了互转的2个工具。 【SHP转TXT】 一、要实现的…

响应式图片与 CSS image-set

响应式图片 前置知识 art direction problem光栅图像与矢量图像 raster image and vector images img 能否担此重任 sizessrcset实际看一看 picture: img 的好姐妹 source实际看一看 CSS image-set 语法兼容性 其他注意事项 响应式图片 图片在网页中占据了 超过 60% 的浏览带…

nodepad++ 插件的安装

nodepad 插件的安装 一、插件安装二、安装插件&#xff1a;Json Viewer nodepad 有 插件管理功能&#xff0c;其中有格式化json以及可以将json作为树查看的插件&#xff1a; Json Viewer 一、插件安装 1、首先下载最新的notepad 64位【https://notepad-plus.en.softonic.com…

VTK——使用ICP算法进行模型配准

ICP算法 迭代最近点&#xff08;Iterative Closest Point&#xff0c;ICP&#xff09;算法是一种用于两个三维形状之间几何对齐&#xff08;也叫做配准&#xff09;的计算方法。通常&#xff0c;这两个形状至少有一个是点云数据。ICP算法用于最小化源点云与目标点云之间点到点…

java企业工程管理系统源码之提高工程项目管理软件的效率

高效的工程项目管理软件不仅能够提高效率还应可以帮你节省成本提升利润 在工程行业中&#xff0c;管理不畅以及不良的项目执行&#xff0c;往往会导致项目延期、成本上升、回款拖后&#xff0c;最终导致项目整体盈利下降。企企管理云业财一体化的项目管理系统&#xff0c;确保…

Golang设计模式

Golang设计模式 Golang设计模式简介Golang工厂设计模式Golang单例设计模式Golang抽象工厂设计模式Golang建造者模式 (Builder Pattern)Golang 原型模式(Prototype Pattern)Golang适配器模式Golang 桥接模式&#xff08;Bridge Pattern&#xff09;Golang装饰器模式(Decorator …

Qt5界面Qt Designer上添加资源图片后,ModuleNotFoundError: No module named ‘rcc_rc‘ 的终极解决方案

在网上找了很久都没弄明白&#xff0c;最后还是自己思考解决了。 起因&#xff1a; 用 Qt Designer 添加资源文件作为背景图&#xff0c;编译 \resource\static\qrc> pyuic5 -o .\xx.py .\xx.ui发现在 xx.py 文件末尾中多了一个语句&#xff1a; import rcc_rc然后运行就…

vue项目——表情选择器

组件库地址&#xff1a;https://www.npmjs.com/package/emoji-mart-vue 1、下载 npm install --save emoji-mart-vue 2、引入 import { Picker } from emoji-mart-vueexport default {components: {Picker} }3、使用 <picker set"emojione" /> <picker …