JavaWeb Servlet实现文件上传与下载功能实例
作者:CoderX(远离BUG) 发布时间:2023-06-16 16:41:27
前言
在上网的时候我们常常遇到文件上传的情况,例如上传头像、上传资料等;当然除了上传,遇见下载的情况也很多,接下来看看我们 servlet 中怎么实现文件的上传和下载。
项目准备
idea:2020.1
jdk:1.8
tomcat:10
项目模板:java Enterprise–>Web Application
文件上传
文件上传涉及到前台页面的编写和后台服务器端代码的编写,前台发送文件,后台接收并保存文件,这才是一个完整的文件上传。
前台页面
在做文件上传的时候,会有一个上传文件的界面,首先我们需要一个表单,并且表单的请求方式为 POST;其次我们的 form 表单的 enctype 必须设为"multipart/form-data",即 enctype=“multipart/form-data”,意思是设置表单的类型为文件上传表单。默认情况下这个表单类型是 “application/x-www-form-urlencoded”, 不能用于文件上传。只有使用了multipart/form-data 才能完整地传递文件数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<!--文件上传
1. 准备表单
2.设置表单提交类型为POST method="POST"
3.设置表单类型为文件上传表单 enctype="multipart/form-data"
4.设置文件提交地址 action地址需要和后台servlet注解保持一致
5.准备表单元素
6.设置表单元素的name属性值(否则后台无法接收数据)
-->
<form method="post" enctype="multipart/form-data" action="upLoadServlet">
姓名:<input type="text" name="uname"><br>
文件:<input type="file" name="myfile"><br>
<!--button默认时提交类型 type="submit"-->
<button>提交</button>
</form>
</body>
</html>
后台实现
使用注解 @MultipartConfig 将一个 Servlet 标识为支持文件上传。 Servlet 将 multipart/form-data 的 POST 请求封装成 Part,通过 Part 对上传的文件进行操作。
package formServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import java.io.IOException;
/*
* 文件上传
* 1.使用注解@MultipartConfig,将servlet标识为支持文件上传
* 2.servlet将muitipart/form-data的POST请求封装成part对象,通过part对文件上传进行操作
*
*/
@WebServlet("/upLoadServlet")
@MultipartConfig //文件上传注解
public class UploadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("文件上传");
//设置请求编码格式
req.setCharacterEncoding("UTF-8");
//获取普通表单元素
String uname=req.getParameter("uname");
System.out.println("uname:"+uname);
//获取part对象
Part part=req.getPart("myfile");
//通过part对象获得上传文件名
String fileName = part.getSubmittedFileName();
System.out.println("file:"+fileName);
//得到文件存放路径
String filePath = req.getServletContext().getRealPath("/");
System.out.println("filePath:"+filePath);
//上传文件到指定路径
part.write(filePath+"/"+fileName);
}
}
提交表单后查看控制台打印结果
文件上传
uname:张三
file:exception.jpg
filePath:E:\bdqn\JavaWeb\servlet\out\artifacts\servlet_war_exploded\
文件下载
文件下载,即将服务器上的资源下载(拷贝)到本地,我们可以通过两种方式下载。第一种是通过超链接本身的特性来下载;第二种是通过代码下载。
资源准备
在web目录下新建文件夹存放下载资源,通过tomcat配置添加Deployment到服务器中
超链接下载
当我们在 HTML 或 JSP 页面中使用a标签时,原意是希望能够进行跳转,但当超链接遇到浏览器不识别的资源时会自动下载;当遇见浏览器能够直接显示的资源,浏览器就会默认显示出来,比如 txt、png、jpg 等。当然我们也可以通过 download 属性规定浏览器进行下载。但有些浏览器并不支持。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<!--
超链接下载
1.当时用超链接(a标签)时,如果遇到浏览器能够识别的内容,会显示内容,而不会进行下载.
指定download属性进行下载;
2.如果遇到浏览器不能识别的内容,会进行下载
-->
<!--浏览器能够识别的资源,显示内容-->
<a href="download/1.txt">文本文件</a>
<a href="download/retrun.jpg">图片文件</a>
<!--压缩文件是浏览器不能识别的资源,进行下载-->
<a href="download/1.zip">压缩文件</a>
<!--浏览器能够识别的资源,设置download属性,进行下载-->
<!--download="文件名.后缀名",不设置文件名和后缀名会默认服务器中的文件属性-->
<a href="download/1.txt" download>文本文件下载</a>
<a href="download/retrun.jpg" download="re.png">图片文件下载</a>
</body>
</html>
download 属性可以不写任何信息,会自动使用默认文件名。如果设置了download属性的值,则使用设置的值做为文件名。当用户打开浏览器点击链接的时候就会直接下载文件。
后台实现下载
实现步骤
需要通过 response.setContentType 方法设置 Content-type 头字段的值, 为浏览器无法使用某种方式或激活某个程序来处理的 MIME 类型,例 如 “application/octet-stream” 或 “application/x-msdownload” 等。
需要通过 response.setHeader 方法设置 Content-Disposition 头的值 为 “attachment;filename=文件名”
读取下载文件,调用 response.getOutputStream 方法向客户端写入附件内容。
package formServlet;
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 java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 文件下载
* 1. 需要通过 response.setContentType 方法设置 Content-type 头字段的值, 为浏览器无法使用某种方式或激活某个程序来处理的 MIME 类型,例 如 "application/octet-stream" 或 "application/x-msdownload" 等。
* 2. 需要通过 response.setHeader 方法设置 Content-Disposition 头的值 为 "attachment;filename=文件名"
* 3. 读取下载文件,调用 response.getOutputStream 方法向客户端写入附件内容。
*/
@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("文件下载...");
//设置请求编码格式
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
//获取参数(下载文件名)
String fileName = req.getParameter("fileName");
System.out.println(fileName);
//参数非空判断 trim():去除字符串的前后空格
if(fileName==null||"".equals(fileName.trim())){
//参数为空,写入浏览器提示
resp.getWriter().write("请输入要下载的文件名!");
resp.getWriter().close(); //关闭流
return; //退出当前
}
//得到文件存放路径
String filePath=req.getServletContext().getRealPath("/download/");
//通过路径得到file对象
File file = new File(filePath + fileName);
//判断文件对象是否存在并且是标准文件
if(file.exists()&&file.isFile()){
//设置响应类型(浏览器无法使用某种方式或激活某个程序来处理的 MIME 类型)
resp.setContentType("application/x-msdownload");
//设置响应头
resp.setHeader("Context-Disposition","attachment;filename="+fileName);
//得到file文件输入流
FileInputStream fis = new FileInputStream(file);
//得到字节输出流
ServletOutputStream sos=resp.getOutputStream();
//定义byte数组
byte[] bytes=new byte[1024];
//定义长度
int len=fis.read(bytes);
//循环输出
while (len!=-1){
sos.write(bytes,0,len);
}
//关闭资源 先打开的后关闭
sos.close();
fis.close();
}else {
resp.getWriter().write("文件不存在,请重试!");
resp.getWriter().close();
}
}
}
来源:https://blog.csdn.net/qq_45925787/article/details/124421317


猜你喜欢
- RocketMQ生产者发送消息分为三种模式RocketMQ生产者发送消息分为三种模式,分别是同步发送,异步发送和单向发送。单向发送,这个就是
- 直接上代码,看下最简单也是最常用的方法,将Object 转为 JSON 以及将Json转为Object方式public class Test
- 今天有朋友问我Struts2中Action必须实现execute方法吗?顺利的回答出来了。其实分两种情况:1)如果你的Action类是继承自
- About Spring开源免费框架,轻量级,非入侵式框架。Spring就是一个轻量级的控制反转(IOC)和面向切片编程(AOP)的框架Ma
- 如果需要在布局中创造一个层叠的概念,那么使用Android系统中的ViewGroup是不够的,但是可以通过改变ViewGroup的绘制顺序实
- 最近好多app都已经满足了沉浸式通知栏, 所谓沉浸式通知栏:就是把用来导航的各种界面操作空间隐藏在以程序内容为主的情景中,通过相对“隐形”的
- 理解C#中的闭包1、 闭包的含义首先闭包并不是针对某一特定语言的概念,而是一个通用的概念。除了在各个支持函数式编程的语言中,我们会接触到它。
- 一、认识AdapterViewFilpper AdapterViewFilpper 继承 了Adapte
- 本篇分享的是springboot多数据源配置,在从springboot v1.5版本升级到v2.0.3时,发现之前写的多数据源的方式不可用了
- MongoDB是介于关系数据库和非关系数据库之间的一种产品,文件的存储格式为BSON(一种JSON的扩展),这里就主要介绍Java通过使用m
- 在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”。异常通常由错误的代码引发,并由能够更正错误的代码进行
- 一、背景日常开发中,有时候需要根据某个 key 加锁,确保多线程情况下,对该 key 的加锁和解锁之间的代码串行执行。大家可以借助每个 ke
- 简单使用redis-zset实现排行榜此方法实现一个根据某字段的查询次数进行排行,查询的次数越多排行越前(从大到小排序),适用于初学者1.添
- 一、对象与内存控制的知识点1.java变量的初始化过程,包括局部变量,成员变量(实例变量和类变量)。2.继承关系中,当使用的对象引用变量编译
- 如图,刚开始报错获取不到bean因为配置文件1、原因一: *.properties等没有值,还是用${变量的}。获取不到,于是把所有值复制到
- 本文实例讲述了Java实现的微信图片处理工具类。分享给大家供大家参考,具体如下:现在 外面核心,图片文章比较少,看了拷贝代码,而用不了,用相
- 前言若你的工程还没有进行基础配置,请查看我的博文Unity 之 ShaderGraph入门使用详解,按照步骤操作完成配置即可,还能顺便学习一
- 1:Xxtea支持中文;2:支持JS和C#加解密之间的互转;一:C#部分class XXTEA2 {
- 您好,我是贾斯汀,欢迎又进来学习啦!【学习背景】学习Java的小伙伴,都知道想要提升个人技术水平,阅读JDK源码少不了,但是说实话还是有些难
- 支付宝上有一个咻一咻的功能,就是点击图片后四周有水波纹的这种效果,今天也写一个类似的功能。效果如下所示:思路:就是几个圆的半径不断在变大,这