文章图片
目录
一、实现文件上传注意:
二、commons-fileupload.jar 常用API介绍说明:
commons 常用API:
源码实现文件上传:
1.注意事项:
2.前端组件:
3.实现步骤:
导入Maven坐标:
运行结果:
三、文件下载解析:
1.文件下载源码实现:
2.Base64 编码和解码操作:
一、实现文件上传注意:
- 提交时,前端使用form标签,method=post请求
- form标签的encType属性值必须为:multipart/form-data值
- form标签中使用 input type=file 添加文件上传
- 编写服务器代码接收(Servlet程序),处理上传的数据
文章图片
encType=multipart/form-data表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器。
二、commons-fileupload.jar 常用API介绍说明: commons-fileupload.jar 需要依赖commons-io.jar 这个包,所以两个包都需要在项目中引入!
- commons-fileupload.jar 下载地址 : FileUpload – Download Apache Commons FileUpload
- commons-io.jar 下载地址 : Commons IO – Download Apache Commons IO
- ServletFileUpload类,用于解析上传的数据
- boolean ServletFileUpload.isMultipartContent(HttpServletRequest request):判断当前上传的数据格式是否是多段的格式。
- public List
parseRequest(HttpservletRequest request):解析上传的数据
- Fileitem类:表示每一个表单项
- boolean FileItem·isFormField():判断当前这个表单项,是否是普通的表单项。还是上传的文件类型true表示普通类型的表单项false表示上传的文件类型
- String FileItem·getFieldName():获取表单项的name属性值
- String FileItem.getString():获取当前表单项的值。
- String FileItem.getName():获取上传的文件名
- void FileItem.write(file):将上传的文件写到参数file所指向的硬盘位置
- 为保证服务器安全,上传文件应当保存在外界无法直接访问的路径(如 WEB-INF 目录下)
- 为防止文件覆盖,要为上传的文件生成一个唯一的文件名(如-时间戳,-uuid,-md5,-位运算算法)
- 要限制上传文件的大小的最大值。
- 可以限制上传文件的类型,在获取上传文件名时,判断后缀名是否合法。
浏览器处理上传文件,是将文件以流的形式提交到服务器端。
commons-fileupload
:Apache 的文件上传组件,取代原生的文件上传流。commons-io
:commons-fileupload 组件依赖于该组件。
- 提交方式:
method=“post”
(post传送的数据量大,可视为不受限制) - 编码类型:
enctype="multipart/form-data"
(表单包含文件上传控件时必须使用)- enctype 属性
application/x-www=form-urlencoded
:默认方式,只处理表单域中的 value 属性值,将表单域中的值处理成 URL 编码方式;multipart/form-data
:以二进制流的方式处理表单数据,除了表单域中的 value 属性值,还会处理表单域的文件内容,将其封装到请求参数中,不会对字符编码;text/plain
:将空格转换为+
号,其它字符不做编码处理,适用于通过表单发送邮件。
- enctype 属性
- 类型:
type=“file”
- 属性:要求具有 name 属性
- 判断表单:是否包含文件上传控件。
- 创建上传文件和临时文件的保存路径。
- 创建 DiskFileItemFactory 对象。
- 设置临时文件夹
- *设置缓冲区大小
- 创建 ServletFileUpload 对象
- 设置 FileItemFactory
- *监听文件上传进度、处理乱码问题、设置单个文件和总共上传文件的最大值
- 解析请求并处理文件传输
- 解析前端请求,将每个表单项解析并封装成 FileItem 对象
- 判断表单项是否为上传文件
- 处理普通文本:
- 获取字段名
- 获取数据流内容
- 处理文件:
- 获取上传文件名
- 生成随机 UUID 作为文件存储路径,并为其生成文件夹
- 通过 IO 流传输文件
commons-fileupload
commons-fileupload
1.4
public class FileServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 判断表单是否包含文件上传控件
if (!ServletFileUpload.isMultipartContent(req)) { // 不包含文件上传控件,即普通表单
return;
}// 创建上传文件的保存路径:外界无法直接访问
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
makeDirIfNotExist(uploadFile);
// 创建临时文件的保存路径
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File tmpFile = new File(tmpPath);
makeDirIfNotExist(tmpFile);
// 1、创建DiskFileItemFactory对象
DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
// 2、创建ServletFileUpload对象
ServletFileUpload servletFileUpload = getServletFileUpload(factory);
// 3、解析请求并处理文件传输
String msg = "";
try {
msg = uploadParseRequest(req, servletFileUpload, uploadPath);
} catch (FileUploadException e) {
e.printStackTrace();
}req.setAttribute("msg", msg);
req.getRequestDispatcher("/success.jsp").forward(req, resp);
}private String uploadParseRequest(HttpServletRequest httpServletRequest, ServletFileUpload servletFileUpload, String uploadPath)
throws FileUploadException, IOException {
String msg = "";
// 解析前端请求,将每个表单项解析并封装成FileItem对象
List fileItems = servletFileUpload.parseRequest(httpServletRequest);
for (FileItem fileItem : fileItems) {
// 判断表单项是否为上传文件
if (fileItem.isFormField()) { // 普通文本
String filedName = fileItem.getFieldName();
// 获取字段名:表单项name属性的值
String value = https://www.it610.com/article/fileItem.getString("UTF-8");
// FileItem对象中保存的数据流内容:即表单项为普通文本的输入值
System.out.println(filedName + ":" + value);
} else { // 上传文件
// ------------------------1、处理文件------------------------String uploadFileName = fileItem.getName();
// 上传文件名
System.out.println("上传的文件名:" + uploadFileName);
if (uploadFileName == null || uploadFileName.trim().equals("")) { // 文件名为空值或空
continue;
// 进入下一轮循环,判断下一个FileItem对象
}String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);
// 文件后缀名
System.out.println("文件信息【文件名:" + uploadFileName + ",文件类型:" + fileExtName + "】");
// 使用UUID保证文件名唯一
String uuidPath = UUID.randomUUID().toString();
// ------------------------2、处理路径------------------------// 存储路径:uploadPath
String realPath = uploadPath + '/' + uuidPath;
// 真实存在的路径
// 给每个文件创建一个文件夹
File realPathFile = new File(realPath);
makeDirIfNotExist(realPathFile);
// ------------------------3、文件传输------------------------// 获得输入流
InputStream is = fileItem.getInputStream();
// 获得输出流
FileOutputStream fos = new FileOutputStream(realPathFile + "/" + uploadFileName);
// 创建缓冲区
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
msg = "文件上传成功!";
fileItem.delete();
// 上传成功,清除临时文件fos.close();
is.close();
}
}return msg;
}private ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
// ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
// 构造方法设置FileItemFactoryServletFileUpload servletFileUpload = new ServletFileUpload();
servletFileUpload.setFileItemFactory(factory);
// 设置FileItemFactory// ------------------------辅助功能------------------------
// 监听文件上传进度
servletFileUpload.setProgressListener(new ProgressListener() {
/**
*
* @param pBytesRead已读取的文件大小
* @param pContentLength文件大小
* @param pItems
*/
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
String percentage = (int) (((double) pBytesRead / pContentLength) * 100) + "%";
System.out.println("总大小:" + pContentLength + ",已上传:" + pBytesRead + "\t" + percentage);
}
});
// 处理乱码问题
servletFileUpload.setHeaderEncoding("UTF-8");
// 设置单个上传文件的最大值
servletFileUpload.setFileSizeMax(1024 * 1024 * 10);
// 10M
// 设置总共上传文件的最大值
servletFileUpload.setSizeMax(1024 * 1024 * 10);
// 10Mreturn servletFileUpload;
}/**
* 获得磁盘文件项目工程,设置缓冲文件夹及缓冲区大小
*
* @param tmpFile 缓冲文件夹
* @return
*/
private DiskFileItemFactory getDiskFileItemFactory(File tmpFile) {
// return new DiskFileItemFactory(1024 * 1024, tmpFile);
DiskFileItemFactory factory = new DiskFileItemFactory();
// ------------------------辅助功能------------------------
factory.setSizeThreshold(1024 * 1024);
// 1M(缓冲区大小):上传文件大于缓冲区大小时,fileupload组件将使用临时文件缓存上传文件
factory.setRepository(tmpFile);
// 临时文件夹
return factory;
}/**
* 如果文件目录不存在,为其创建目录
*
* @param file
*/
private void makeDirIfNotExist(File file) {
if (!file.exists()) {
file.mkdir();
}
}
}
运行结果: 上传的文件会保存在 Target 目录下对应项目的保存路径下。
文章图片
非临时文件:
- 保存在 upload 文件夹下。
- 文件格式和文件名与上传文件完全相同。
- 每个文件存储在一个子文件夹中,文件夹名是随机生成的 UUID。
文章图片
临时文件:
- 保存在 upload 文件夹下,同时在tmp文件夹下生成一个临时文件。
- upload 文件夹下的文件:文件格式和文件名与上传文件完全相同。
- tmp 文件夹下的文件:tmp 格式,文件名是随机生成的 UUID,在 Servlet 运行到 fileItem.delete() 方法时被清除。、
文章图片
三、文件下载解析: 1.文件下载源码实现: 资源位置保存在web目录下的file文件目录!
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 下载的文件
// 以’/'开头则是从工程路径下获取。
String file = "/file/computer.png";
// 获取下载的文件内容
ServletContext servletContext = getServletContext();
// 获取要下载文件的文件类型
String mimeType = servletContext.getMimeType(file);
// 通过响应头告诉客户端返回的数据类型
resp.setContentType(mimeType);
// 告诉客户端收到的数据适用于下载的
// Content-Disposition表示收到的数据怎么处理
// attachment表示下载使用,filename=文件名 表示指定下载文件的文件名
// encode避免文件名为中文出现乱码
resp.setHeader("Content-Disposition", "attachment;
filename=" + URLEncoder.encode(file.substring(file.lastIndexOf('/') + 1),"UTF-8"));
// 获取需下载的文件的输入流
InputStream inputstream = servletContext.getResourceAsStream(file);
// 获取响应的输出流
ServletOutputStream outputStream = resp.getOutputStream();
// 输入流的数据复制给输出流,输出给客户端
// org.apache.commons.io的工具类
IOUtils.copy(inputstream, outputStream);
}
注意:
getResourceAsStream
读取的文件路径只局限与工程的源文件夹中,但是如果配置文件路径是在除了源文件夹之外的其他文件夹中时,该方法是用不了的。如果省去了
resp.setHeader()
这行代码,图片会直接在该网页上显示2.Base64 编码和解码操作:
final Base64.Decoder decoder = Base64.getDecoder();
final Base64.Encoder encoder = Base64.getEncoder();
final String text = "字串文字";
final byte[] textByte = text.getBytes("UTF-8");
//编码
final String encodedText = encoder.encodeToString(textByte);
System.out.println(encodedText);
//解码
System.out.println(new String(decoder.decode(encodedText), "UTF-8"));
final Base64.Decoder decoder = Base64.getDecoder();
final Base64.Encoder encoder = Base64.getEncoder();
final String text = "字串文字";
final byte[] textByte = text.getBytes("UTF-8");
//编码
final String encodedText = encoder.encodeToString(textByte);
System.out.println(encodedText);
//解码
System.out.println(new String(decoder.decode(encodedText), "UTF-8"));
文章图片
【#|【JavaWeb】文件的上传和下载】
推荐阅读
- 图解Redis|什么是缓存雪崩、击穿、穿透()
- 一日为期,极行千里 ——「企业级零代码黑客马拉松」正式启动报名
- C语言进阶|人人都看得懂的C语言进阶系列之数据存储
- C语言基础|【Visual Studio 2019】 实用调试技巧,学会了都说好
- C语言基础|【C语言入门必看】指针
- C语言基础|【C语言入门必看】结构体
- Kubernetes|Kubernetes 中的服务发现与负载均衡
- Wordpress|百度提交网站提示您无权访问该页面,点击确定按钮返回首页,如何解决
- java|java 蓝桥杯 输出组合_Java蓝桥杯——排列组合