- Tomcat 9
文件上传
-
文件上传本质上是 I/O 读写
- 客户端(浏览器)发送文件使用 HTTP 协议,将文件的内容写出去:客户端本地输入流 > 内容 > 网络输出流
- 服务器(Web容器)接收文件使用 HTTP 协议,将文件的内容读过来:网络输入流 > 内容 > 服务器本地输出流
-
一般使用外部包进行文件上传,常用的是 apache 组织提供的两个包
文件上传的步骤
知识补充:get 与 post 虽然对字节数都没有限制
- 但 get 通过 URL 拼串,而不同浏览器对于 UR L处理长度有所不同
- 但 post 需要 Web 容器的支持,与容器的处理性能有关,比如 Tomcat 默认无限制,但是可以通过修改 server.xml 配置文件中的
<Connector port="8080" maxPostSize="-1">
浏览器端
- JSP/HTML 文件中,表单通过 post 提交(不能使用 get,是由于 ServletFileUpload 类的规定)
- 表单中添加一个属性
enctype="multipart/form-date"
- 表单中使用
<input type="file">
组件让用户选择上传的文件,不仅仅能得到文件名还可以将文件的内容读出来
服务器端
-
引入文件上传需要的jar包
-
控制层
//1.创建一个工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.创建一个 ServletFileUpload 对象,包含一个 factory
ServletFileUpload upload = new ServletFileUpload(factory);
//3.使用 upload 对象解析 request,得到一个 List<FileItem>
List<FileItem> itemList = upload.parseRequest(request);
- 业务逻辑
- 对普通组件与文件的处理方式
for (FileItem item: itemList) {
if (item.isFormField()) { //是普通组件
String key = item.getFieldName(); //获取组件的 name 属性
String value1 = item.getString(); //获取组件的 value 属性
String value2 = item.getString("UTF-8"); //该重载方法可以处理字符集
} else { //是文件
String fileName = item.getName(); //获取上传文件的真实文件名
InputStream inputStream = item.getInputStream(); //读取网络输入流
item.write(new File("文件路径")); //写,即保存上传的文件
}
}
- 注意:如果上传的文件较大,为了防止丢包会产生临时文件(Tomcat 容器默认存在 temp 文件夹下)
factory.setSizeThreshold(10240); //设置缓冲区大小,默认10240byte - 10KB
factory.setRepository(new File("路径")); //设置缓冲区位置
- 还可以设置上传文件的大小限制(为了缓解服务器存储压力)
upload.setFileSizeMax(); //单个上传文件的大小限制
upload.setSizeMax(); //上传文件总大小限制
- 监控文件上传进度
upload.setProgressListener(new ProgressListener(){
//文件上传字节数达到4096个字节,就触发一次监听器
public void update(long l, long l1, int i) {
//第一个参数表示 已经上传的字节个数
//第二个参数表示 上传文件的总字节数
//第三个参数表示 正在上传第几个组件
...
}
});
文件上传注意事项
- 浏览器端需要满足四个条件:form表单、post请求、enctype属性、file组件(一个或多个)
- 服务器端需要满足:factory工厂对象、upload对象、解析request方法得到
List<FileItem>
- 上传文件保存的路径
- 放在一个固定的位置,可移植性不好
- 放在当前工程的根目录下
String path = this.getServletContext().getRealPath("/");
- 最好限制一下文件上传的大小:单个、总体、缓冲区
- 如果文件上传出现文件名冲突的问题
- 方法一:原来名字+用户+时间.原来后缀
beauty_zgh_date.jpg - 方法二:用一个随机产生的名字当做保存在服务器中的文件名
beauty.jpg > xxxxx.jpg
然后将 beatuy、xxxxx、路径、用户、上传时间 它们的关联存起来 - 方法三:一个随机名字创建一个文件夹
beauty.jpg 放在文件夹里
然后将 路径、用户、文件夹名、上传时间 它们的关联存起来
- 方法一:原来名字+用户+时间.原来后缀
- 有些时候可能上传的文件需要控制文件类型
自己设计方法
文件下载
文件下载就很简单了
浏览器端
发送请求,一般通过 a 标签
服务器端
- 接收需要下载的文件名
- 找到文件并创建输入流读取内容
- 处理一下响应时的中文字符
- 设置响应内容类型和状态
- response 创建输出流将内容响应回浏览器
如果服务端存储的文件名字含有中文,需要处理一下
fileName = URLEncoder.encode(fileName,"UTF-8");
文件下载实质上就是服务器向浏览器返回文件信息,如果想看到浏览器跳出弹出框
response.setContentType("application/x-msdownload");
response.setHeader("Content-disposition", "attachment;filename=" + fileName); //fileName变量存储文件名