引言:平凡的生活中拥有一颗不甘于平凡的内心。
此篇文章,写的内容为文件的上传和下载,先写上传下载的位置为tomcat服务器,后期在填补位置在数据库的。
一、基于servlet实现
具体的步骤
代码语言:javascript复制1、要有form标签,method必须=post请求
2、form标签的enctype的属性值必须为multipart/form-data
3、在form标签中使用input type=file 添加上传的文件
4、编写服务器代码接受,处理上传的数据
文件上传时发送的HTTP协议内容,摘录部分:
代码语言:javascript复制Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryTGxWXycKE3KZEeGq
enctype="multipart/form-data" 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以
二进制流的形式发送给服务器。
boundary 表示每段数据的分隔符
----WebKitFormBoundaryTGxWXycKE3KZEeGq 是由浏览器每次随机生成,就是每段数据的分界符
index.jsp
代码语言:javascript复制演示
<h2>文件上传下载演示</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br>
头像:<input type="file" name="photo"><br>
<input type="submit" value="提交">
</form>
后端接收的时候,仅用于调试,理解
代码语言:javascript复制// 以流的形式接收
ServletInputStream inputStream = req.getInputStream();
byte[] buffer = new byte[1024000];
int read = inputStream.read(buffer); // 读了多少个字节
System.out.println(new String(buffer,0,read)); // 缓冲区放进来 从0开始读 read是读的长度
1、导包
commons-io commons-fileupload
创建一个maven工程,勾选模板,导入依赖
依赖如下:
代码语言:javascript复制 <dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
2、常用类和方法
代码语言:javascript复制 ServletFileUpload类下的方法
判断当前上传的数据格式是否是多段的格式
boolean isMultipartContent(HttpServletRequest request)
FileItem类下的方法
解析上传的数据
public List<FileItem> parseRequest(HttpServletRequest request)
判断当前这个表单项,是否是普通的表单项,还是上传的文件类型。
true 表示普通类型的表单项
false 表示上传的文件类型
boolean isFormField();
获取表单项的name值
String getFieldName();
获取当前表单项的值
String getFieldName();
获取上传的文件名
String getName();
将上传的文件写到参数file所指向的磁盘位置
void write(File file)
3、实现
代码语言:javascript复制新建了三个类
TestBase64 测试Base64编码
UploadServlet 上传
Download 下载
配置web.xml
UploadServlet.java
代码语言:javascript复制package com;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
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 {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置页面编码 请求和响应的编码都为UTF-8 否则中文图片名上传的时候会乱码
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8");
System.out.println("文件上传了");
// 1、先判断上传的数据是否是多段数据 (只有是多段的数据才是文件上传的)
if(ServletFileUpload.isMultipartContent(req)){
// 2、创建 FileItemFactory 工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 3、创建用于解析上传数据的工具类 ServletFileUpload
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
try {
// 4、调用解析方法,解析上传的数据,得到每一个表单项 fileItems
List<FileItem> fileItems = servletFileUpload.parseRequest(req);
// 循环判断,每一个表单项,是普通类型还是上传的文件
for (FileItem fileItem : fileItems) {
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:AllTempdata
fileItem.write(new File("D://AllTemp/data/" fileItem.getName()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Download.java
代码语言:javascript复制package com;
import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Encoder;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
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;
import java.net.URLEncoder;
public class Download extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取要下载的文件名
String downloadFileName = "1.jpg";
// 2、读取要下载的文件内容(通过ServletContext对象可以读取)
ServletContext servletContext = getServletContext();
// 获取要下载的文件类型
String mimeType = servletContext.getMimeType("/file/" downloadFileName);
System.out.println("下载的文件类型:" mimeType); // 下载的文件类型:image/jpeg
// 4、在回传前,通过响应头告诉客户端返回的数据类型
resp.setContentType(mimeType);
// 5、还要告诉客户端收到的数据是用于下载使用(还是使用响应头)
// Content-Disposition 表示收到的数据怎么处理
// attachment 表示附件 ,下载使用
// filename 表示指定下载的文件名
// resp.setHeader("Content-Disposition","attachment;filename=" downloadFileName);
// 可支持下载中文 文件名
// URL 解决IE和谷歌的下载 中文乱码问题
// BASE64 解决火狐浏览器的下载 中文乱码问题
// 设置URL编码 URL编码是把汉字转化为%xx%xx的格式
// resp.setHeader("Content-Disposition","attachment;filename=" URLEncoder.encode("风景图片999.jpg","UTF-8"));
// 解决火狐浏览器的下载 中文乱码问题 需要修改请求头
// Content-Disposition: attachment;filename==?charset?B?xxxxx?=
// =?charset?B?xxxxx?= 进行说明
// =? 表示编码内容的开始
// charset 字符集
// B 表示BASE64编码
// xxxxx 表示文件名BASE64编码后的内容
// ?= 表示编码内容的结束
// resp.setHeader("Content-Disposition","attachment;filename==?UTF-8?B?" new BASE64Encoder().encode("风景图片999.jpg".getBytes( "UTF-8")) "?=");
// 请求头信息 进行判断 火狐或谷歌
// User-Agent
// Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0
if(req.getHeader("User-Agent").contains("Firefox")){
// 如果是火狐浏览器使用 Base64编码
resp.setHeader("Content-Disposition","attachment;filename==?UTF-8?B?" new BASE64Encoder().encode("风景图片999.jpg".getBytes( "UTF-8")) "?=");
}else {
// 如果不是火狐 ,是谷歌或IE 使用URL编码
resp.setHeader("Content-Disposition","attachment;filename=" URLEncoder.encode("风景图片999.jpg","UTF-8"));
}
// 这里放文件的路径 /斜杠被服务器解析表示 http://ip:端口号/工程名/ 映射到 代码的 web目录
// 我是在webapp下新建文件夹file 里面放了一张图片 图片名1.jpg
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" downloadFileName);
// 获取响应的输出流
ServletOutputStream outputStream = resp.getOutputStream();
// 3、把下载的文件内容回传给客户端
// 读取输入流中全部的数据,复制给输出流,输出给客户端
IOUtils.copy(resourceAsStream,outputStream);
}
}
TestBase64.java
代码语言:javascript复制package com;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class TestBase64 {
public static void main(String[] args) throws Exception {
String content = "这是一段中文使用base64编码的内容";
// 创建一个Base64编码器
BASE64Encoder base64Encoder = new BASE64Encoder();
// 执行Base64编码操作 对字节数组进行操作
String encode = base64Encoder.encode(content.getBytes("UTF-8"));
System.out.println(encode); // 6L Z5piv5LiA5q615Lit5paH5L2/55SoYmFzZTY057yW56CB55qE5YaF5a65
// 创建Base64解码器
BASE64Decoder base64Decoder = new BASE64Decoder();
// 解码操作
byte[] bytes = base64Decoder.decodeBuffer(encode);
String s1 = new String(bytes,"UTF-8");
System.out.println(s1); // 这是一段中文使用base64编码的内容
}
}
web.xml
代码语言:javascript复制 <servlet>
<servlet-name>upload</servlet-name>
<servlet-class>com.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>upload</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>download</servlet-name>
<servlet-class>com.Download</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>download</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>