文件上传下载

配套视频https://www.bilibili.com/video/BV14Z4y1p763?p=1&vd_source=3558fd85254f40ca0361146cc92d2cce

1、文件上传

1.1 提出问题

客户需要将自己的文件上传给服务器怎么处理? 文件上传的时候是怎样提交给服务器的?
答:我们可以使用 multipart/form-data 表单处理文件上传,文件的上传是以流的形式提交给服务器的

1.2 文件上传步骤

文件上传我们需要用到两个包。commons-fileupload-1.3.1.jar、commons-io-2.4.jar。 所以先导入包。然后进行文件上传测试
文件上传步骤:
1)修改表单 enctype 值为 multipart/form-data,并且 method=post

<form action="upload" method="post" enctype="multipart/form-data"> 
	<input type="file" name="file"> 
	<input type="submit"> 
</form>

2)创建文件上传请求解析器
在 doPost 方法中创建 ServletFileUpload 对象,并传入 DiskFileItemFactory 工厂对象

DiskFileItemFactory factory = new DiskFileItemFactory(); 
ServletFileUpload fileUpload = new ServletFileUpload(factory);

3)解析并上传文件
解析上传文件请求

List<FileItem> list = fileUpload.parseRequest(request);
 for(FileItem f : list){ 
	 if(f.isFormField()){
	 //普通表单项
	 }else{ 
	 //文件表单项 
	 String name = f.getName(); 
	 System.out.println(name); 
	 f.write(new File("D:/"+name));
    } 
}

注意事项:
①、当文件上传表单的文件项未选择文件时,文件大小为 0,应该做判断,当文件 大小为 0 则不进行上传
②、使用 fileItem.getName()获取文件名。在火狐谷歌下,为文件的名字。在 ie 下为 文件的路径,因此要获取文件名需要进行处理
③、使用 fileItem.getString(“utf-8”),获取文件普通表单项的值

完整的文件上传代码

protected void doPost(HttpServletRequest request,HttpServletResponse response) throws
ServletException, IOException {
	// 1、创建fileItem工厂
	DiskFileItemFactory factory = new DiskFileItemFactory();
	// 2、创建文件上传对象
	ServletFileUpload fileUpload = new ServletFileUpload(factory);
	// 3、解析文件上传请求
	try {
		List<FileItem> list = fileUpload.parseRequest(request); 
		// 4、遍历解析出的每个FileItem文件
		for (FileItem f : list) { 
			// 这是普通表单项
			if (f.isFormField()) { 
				// 表单项的name值
				String fieldName = f.getFieldName(); 
				// 表单项value,使用编码取得中文 
				String fieldValue = f.getString("utf-8"); 
				System.out.println(fieldName + ":" + fieldValue);
			// 表示文件表单项 
			} else {
				//获取文件大小,有可能并没有上传文件 
				long size = f.getSize(); 
				if(size == 0){ 
					continue; 
				}
				// 获取文件名字 
				String name = f.getName(); 
				// ie下是全路径,火狐谷歌为文件名,需要不同处理 
				if (name.contains("\\")) { 
				name = name.substring(name.lastIndexOf("\\") + 1); 
				}
				//获取文件保存的服务端路径 
				String realPath = request.getServletContext().getRealPath("/upload"); 
				File file = new File(realPath); 
				if(!file.exists()){ 
				file.mkdirs(); 
				}
				//生成一个唯一不重复的文件名 
				name = UUID.randomUUID().toString().replace("-", "")+"-"+name; 
				//将文件内容写入 
				f.write(new File(realPath+"/"+name));
			} 
		} 
	} catch (FileUploadException e) {
		e.printStackTrace(); 
	} catch (Exception e) { 
		e.printStackTrace(); 
	}
	response.setContentType("text/html;charset=UTF-8"); 
	response.getWriter().write("上传完成!"); 
}

其他注意

fileUpload 可以来限制文件的大小 :

//1、设置当文件的大小为 50KB 
fileUpload.setFileSizeMax(1024*50); 

//2、设置多个文件的总大小为 150KB 
fileUpload.setSizeMax(1024*150);

当文件超出大小限制的时候会抛出异常,增加 catch 子句来处理
catch (SizeLimitExceededException e) { 
	response.setContentType("text/html;charset=UTF-8"); 
	response.getWriter().write("文件大小超出限制"); 
	return; 
}

1.3 原理

分析文件上传的请求我们会发现,文件上传的时候 request 的 body 会增加一个分界符,分界符用来分割正常的表单域和文件表单域,文件的内容在分界符的中间,以流的形式传递,文件上传的 request 请求如下:
在这里插入图片描述以上是请求头;

2、文件下载

2.1 提出问题

如何把服务器上的文件传输给客户端。href 可以吗?
1、href 可以传送某些资源,当客户端不支持此资源的显示或者打开时,就会启动下载。
2、但是如果客户端支持显示或者打开此资源。如: 图片,视频,音频,文本文件等。浏览器会直接打开他们。我们需要浏览器进行下载操作。 所以单纯的 href 已经不能操作了。
3、如果资源文件是比较重要的文件,我们需要放到 WEB-INF 下将其保护,那么 href 是链接不到的。

2.2 文件下载步骤

2.2.1 下载步骤

1)设置响应体 
response.setContentType(this.getServletContext().getMimeType("abc.txt")); 
//表示是一个附件
response.setHeader("Content-Disposition", "attachment;filename="+"abc.txt"); 
2)输出文件流 
FileInputStream fis = new FileInputStream(this.getServletContext().getRealPath("/abc.txt")); 
ServletOutputStream stream = response.getOutputStream(); 
//使用commons.io工具输出流
IOUtils.copy(fis, stream); 
fis.close()

2.2.2 存在的问题

1)文件名为中文
使用 URLEncoder.encode 方法将文件名进行编码
String fileName = URLEncoder.encode(“中文.txt”,“utf-8”);
response.setHeader(“Content-Disposition”, “attachment;filename=”+fileName);

火狐不支持,显示格式不正确

火狐需要使用 base64 编码,加上 utf-8 标注。 
String fileName = ""; 
String header = request.getHeader("User-Agent"); 
if(header.contains("Firefox")){ 
	fileName = "=?utf-8?b?"+new BASE64Encoder().encode(name.getBytes("utf-8"))+"?="; 
}else{ 
	fileName = URLEncoder.encode("中文.txt","utf-8"); 
}

先用 GBK 解码,再使用 iso8859-1 编码

String fileName = new String(name.getBytes("gbk"),"iso8859-1"); 
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值