一、文件的上传
文件的上传,是通过表单form的形式进行的,正常的提交流程需要满足3个条件,即文件上传从头至尾的步骤如下:
1.1 表单进行限制:
<form>
中文件的属性设置包含如下:
- 指定 enctype = multipart/form-data
- 指定 method = post
<form action="/day12/uploadServlet2" method="post" enctype="multipart/form-data">
用户名:<input name="username" ><br>
上传头像:<input type="file" name="f" ><br>
<input type="submit" value="提交">
</form>
设置后,HTTP的请求体的信息如下:
-----------------------------7df29b39704fa
Content-Disposition: form-data; name="username"
zhangsan
-----------------------------7df29b39704fa
Content-Disposition: form-data; name="f"; filename="Desert.jpg"
Content-Type: image/jpeg
<二进制文件数据未显示>
---------------------------7df29b39704fa--
1.2对Servlet的限制
- 不能使用getParameter获取请求参数。即使要使用 获取的也是null
- 使用 getInputStream()获取消息体数据
然后解析消息体,就可以来获取我们需要的数据了
1.3解析数据:
解析数据分为普通的表单数据和文件的表单数据,其中文件的表单数据解析方式和XML的解析步骤差不多
- 导包 file-upload 组件:apache
- commons-fileupload-1.2.1.jar
- commons-io-1.4.jar
- 创建解析器工厂
- 获取解析器
- 解析request。获取 List
- 遍历集合
- 使用FileItem方法获取数据
- 普通表单项
- getString(String encoding):获取普通表单项的值
- 文件表单项
- getName():获取文件名称
- getSize():获取文件大小
- getContentType():获取文件类型
- getOutputStream():获取文件字节数据
- write(java.io.File file) :将文件数据写到硬盘上
- 公共方法
- isFormField():判断是否为普通表单项
- getFieldName():获取表单项的名称
- 普通表单项
//1.创建解析器工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2.获取解析器
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("utf-8");
//3.解析request
List<FileItem> fileItems = upload.parseRequest(request);
//4.遍历
for (FileItem fileItem : fileItems) {
System.out.println("--------------------");
String fieldName = fileItem.getFieldName();
System.out.println(fieldName);
if(fileItem.isFormField()){
//普通表单项
String value = fileItem.getString("utf-8");
System.out.println(value);
}else{
//文件表单项
String name = fileItem.getName();
long size = fileItem.getSize();
String contentType = fileItem.getContentType();
String filename = "/"+UUIDUtils.getUUID() + "_" + name;
fileItem.write(new File(this.getServletContext().getRealPath("/upload"+filename)));
System.out.println(name+size+contentType);
}
}
二、文件的下载
- 超链接直接指向资源
如果浏览器有解析引擎支持文件格式,就直接在浏览器中打开。反之,则弹出下载提示框。这各方式不对响应头进行处理,所以打开方式不可以控制。
<a href="/day12_2/a.jpg">图片</a>
<a href="/day12_2/a.avi">电影</a>
- 通过response输出流
这种方式,把请求提交到servlet进行处理。通过servlet设置response响应头的方式,可以控制浏览器的打开方式,从而可以让用户选择“打开”或者“保存”。
<a href="/day12_2/download?filename=哈哈.jpg">图片</a>
<a href="/day12_2/download?filename=a.avi">电影</a>
- 两个响应头:
- content-disposition:attachment;filename=xxx
- inline:默认值。在浏览器中打开
- attachment;filename=xxx:弹出下载提示框
- content-type:文件的格式
- content-disposition:attachment;filename=xxx
- 一个流:文件关联后,通过response输出流,把文件
// 1.获取文件名称
String filename = request.getParameter("filename");
filename = new String(filename.getBytes("iso-8859-1"), "utf-8");
// 2.通过名称获取文件对象
String filepath = this.getServletContext().getRealPath("/" + filename);
// 3.创建输入流关联文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
filepath));
// 4.设置两个头
//获取浏览器的版本信息,解决浏览器的兼容性问题
String agent = request.getHeader("user-agent");
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?"
+ base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else if (agent.contains("Chrome")) {
// google浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
/*// 中文名称在浏览器的下载提示框中不显示问题
filename = URLEncoder.encode(filename, "utf-8");*/
response.setHeader("content-disposition", "attachment;filename="
+ filename);
response.setContentType(this.getServletContext().getMimeType(filename));
// 5.将输入流数据 拷贝到 response输出流中
IOUtils.copy(bis, response.getOutputStream());