javaWeb
文件上传与下载
理论(原理分析):
文件下载
- 要获取下载文件的路径
- 下载的文件名(显示给客户端的文件名)
- 设置想办法让浏览器能够支持下载我们需要的东西(
attachment;filename
) - 创建文件输入流
- 创建缓冲区
- 获取
OutputStream
对象 - 将
FileOutputStream
流写入到buffer
缓冲区 - 使用
OutputStream
将缓冲区中的数据输出到客户端!
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 要获取下载文件的路径
String realPath = "F:\\班级管理\\西开【19525】\\2、代码\\JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\秦疆.png";
System.out.println("下载文件的路径:"+realPath);
// 2. 下载的文件名是啥?
String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
// 3. 设置想办法让浏览器能够支持(Content-Disposition)下载我们需要的东西,中文文件名URLEncoder.encode编码,否则有可能乱码
resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
// 4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
// 5. 创建缓冲区
int len = 0;
byte[] buffer = new byte[1024];
// 6. 获取OutputStream对象
ServletOutputStream out = resp.getOutputStream();
// 7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区中的数据输出到客户端!
while ((len=in.read(buffer))>0){
out.write(buffer,0,len);
}
in.close();
out.close();
}
注意:设置头时attachment;filename
的分号如果不小心写成冒号,则只会显示图片而不是下载图片
文件上传
需要的依赖包
-
commons.io
<!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency>
-
commons.fileupload
(依赖于``commons.io`)<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency>
需要用到的类
ServletFileUpload
负责处理上传文件数据,并将表单每个输入项封装成一个FileItem`对象,在使用`ServletFileUplead`对象解析请求时需要`DiskFileItemFactory`对象。所以我们需要在进行解析工作前构造好`DiskFileItemFactory`对象,通过`ServletFileUpload`对象的构造方法或`setFileItemFactory()
方法设置ServletFileUpload
对象的fileItemFactory
属性
FileItem
类
在HTML页面input必须要有name<input type="file" name="filename">
表单如果包含一个文件上传输入项的话,这个表单的enctype
属性就必须设置为multipart/form-data
<form action="" enctype="multipart/form-data" method="post">
上传用户<input type="text" name="username"><br/>
<p><input type="file" name="file1"></p>
<p><input type="file" name="file2"></p>
<p><input type="submit"> | <input type="reset"></p>
</form>
常用方法
//isFormField方法用于判断FileItem类地下封装的数据是一个普通文本表单
//还是一个文件表单,如果是普通表单字段则返回true,否则返回false
boolean isFormField();
//getFiledName()方法用于返回表单标签name属性的值。
String getFieldName();
//getString()方法用于将FileItem对象中保存的数据流内容以一个字符串返回
String getString();
//getName()方法用于获得文件上传字段中的文件名
String getName();
//以流的形式返回上传文件的数据内容。
InputStream getInputStream();
//delete方法用来清空FileItem类对象中存放的主体内容
//如果主体内容被保存在临时文件中,delete方法将删除该临时文件。
void delete();
ServletFileUpload
类
ServletFileUpload
负责处理上传的文件数据,并架构表单中每个输入项封装成一个FileItem
对象中,使用其**parseRequest(HttpServletRequest r)
**方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem
对象,然后以List
列表的形式返回。使用该方法处理上传文件简单易用。
package com.example.file;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;
@WebServlet(name = "FileServlet", value = "/FileServlet")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//判断上传的文件时普通表单还是带文件的表单
if (!ServletFileUpload.isMultipartContent(request)) {
return;//终止方法运行,说明这是个普通表单,直接返回
}
//创建上传文件的保存路径 建议保存到WEB-INF路径下 安全 用户无法直接访问上传的文件
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
File uploadFile = new File(uploadPath);
if (!uploadFile.exists()) {
uploadFile.mkdir();//创建这个目录
}
//缓存,临时文件
String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
File tmpFile = new File(tmpPath);
if (!tmpFile.exists()) {
tmpFile.mkdir();//创建这个临时目录
}
//处理上传的文件
/*
ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象
在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象
所以 Wimbledon需要在进行解析工作前构造好DiskFileItemFactory对象
通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性
*/
DiskFileItemFactory factory = getDiskFileItemFactory(tmpFile);
ServletFileUpload servletFileUpload = getServletFileUpload(factory);
String result = extracted(request, uploadPath, servletFileUpload);
request.setAttribute("result",result);
System.out.println(result);
request.getRequestDispatcher("info.jsp").forward(request,response);
}
private String extracted(HttpServletRequest request, String uploadPath, ServletFileUpload servletFileUpload){
StringBuilder msg = new StringBuilder();
try{
//3.处理上传的文件
//吧前端请求解析 封装成一个FileItem对象
List<FileItem> fileItems = servletFileUpload.parseRequest(request);
for (FileItem fileItem : fileItems) {
String name;
if(fileItem.isFormField()){
//getFileName指的是前端表单控件Name
name = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");//处理乱码
System.out.println(name+":"+value