WEB上传下载
一、上传
1.1上传的要求
- 上传在form标签完成
- 必须为post请求(get请求有大小有限制)
- form标签中的encType属性必须为multipart/form-data值
- input的类型type=file表示要上传的文件
- 编写服务器接收,处理上传的文件与表单数据
encType=multipart/form-data 表示提交的数据,以多段(每一个表单项表示一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器
1.2 HTTP协议说明
1.3 文件上传
导入commons-fileupload.jar与commons-io.jar
常用类:
-
ServletFileUpload:解析上传的数据
- static boolean isMultipartContent(HttpServletRequest request):判断当前上传的数据格式是否为多段的格式
- List < FileItem > parseRequest((HttpServletRequest request):解析上传的数据,返回一个LIst集合代表form表单的所有项
-
FileItem:代表每一个表单项
- boolean isFormField():判断当前这个表单项,是否是普通的表单项。还是上传的文件类型,true 表示普通类型的表单项
- String getFieldName():获取表单项的 name 属性值
- String getString():获取当前表单项的value值
- String getString(String encoding):获取当前表单项的value值并设置其字符编码
- String getName():获取上传的文件名
- void write(File file):将上传的文件写出到硬盘
前台页面
<form action="${pageContext.request.contextPath}/upload" method="post"
enctype="multipart/form-data">
用户名:<input name="name" > <br>
上传文件:<input type="file" name="fileName">
<input type="submit">
</form>
服务器
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
//设置请求、响应的编码
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//断当前上传的数据格式是否为多段的格式
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart){
System.out.println("上传格式不是Multipart");
return ;
}
FileItemFactory fileItemFactory = new DiskFileItemFactory();
//创建ServletFileUpload对象,需要FileItemFactory对象
ServletFileUpload upload = new ServletFileUpload(fileItemFactory);
List list = null ;
try {
//解析上传的数据,得到form表单的所有项
list = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
//使用迭代器遍历
Iterator iterator = list.iterator();
while (iterator.hasNext()){
//强转为FileItem类型
FileItem fileItem = (FileItem)iterator.next();
//判断是否为普通的表单项
if (fileItem.isFormField()){
String fieldName = fileItem.getFieldName();
String value = fileItem.getString("utf-8");
System.out.println(fieldName+"=="+value);
}else {//为文件类型
//获取文件名称
String fileName = fileItem.getName();
//截取文件类型
fileName = fileName.substring(fileName.lastIndexOf('.'));
try {
//将上传的文件写出到硬盘
fileItem.write(new File("F:\\"+randomName()+fileName));
//删除内存中的临时文件
fileItem.delete();
fileItem.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//随机生成5为数的String类型
private static String randomName(){
int i = (int)(Math.random()*89999)+10000;
String str = i+"";
return str ;
}
二、下载
2.1步骤
- 下载的文件路径
- 下载的文件的文件名
- 设置浏览器能支持下载的操作(设置响应头)
- 读入下载的文件
- 写出下载的文件
- 关闭资源
设置响应头
- response.setHeader(“Content-Disposition”, “attachment; fileName=文件名”);
- 这个响应头告诉浏览器。这是需要下载的
- attachment 表示附件
- fileName=文件名, 表示下载的文件名
如果下载的文件是中文名的话,下载无法正确显示出正确的中文名。原因是在响应头中,不能包含有中文字符,只能包含 ASCII 码。
因此需要设置字符编码
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
//1、需要下载的文件路径
String path = "D:\\BaiduNetdiskDownload\\java web\\资料\\10-项目第三阶段\\笔记\\文件上传和下载\\ASCII码表I.jpg";
//2、下载的文件的文件名
String fileName = path.substring(path.lastIndexOf("\\")+1);
//3、设置浏览器能支持下载的操作(设置响应头) -- URLEncoder.encoder("文件名","字符集")设置中文编码
try {
response.setHeader("Content-Disposition","attachment;fileName="+URLEncoder.encode(fileName,"utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
InputStream in = null;
OutputStream out = null;
try {
//4、读入下载的文件
in = new FileInputStream(path);
out = response.getOutputStream();
//5、设置缓冲区
byte[] buffer = new byte[1024] ;
int reader = 0 ;
//6、写出下载的文件
while((reader=in.read(buffer))!=-1){
out.write(buffer,0,reader);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//7、关闭IO流
if (out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (in!=null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.2 中文乱码问题
1、IE和谷歌浏览器
浏览器是 IE 浏览器 或者 是谷歌浏览器,要使用 URLEncoder 类先对中文名进行 UTF-8 的编码操作
String str = "attachment: fileName=" + URLEncoder.encode("中文.txt","UTF-8");
response.setHeader("Content-Disposition",str);
2、火狐浏览器
浏览器是火狐浏览器。 需要对中文名进行 BASE64 的编码操作
filename = “=?charset?B?xxxxx?=” 含义
- “=?” 表示编码的开始
- “charset” 表示字符集
- B 表示BASE64编码
- “xxxx” 表示编码的内容(BASE64编码的文件名)
- “?=” 表示编码内容的结束
//使用BASE64 编码后的文件名
String nameEncoding = new BASE64Encoder().encode("文件名".getBytes("UTF-8"));
String str = "attachment;fileName=" + "=?utf-8?B?" + nameEncoding + "?=";
//设置到响应头中
resp.setHeader("Content-Disposition",str);
码后的文件名
String nameEncoding = new BASE64Encoder().encode(“文件名”.getBytes(“UTF-8”));
String str = “attachment;fileName=” + “=?utf-8?B?” + nameEncoding + “?=”;
//设置到响应头中
resp.setHeader(“Content-Disposition”,str);