Web基础笔记Day07 文件上传下载

文件上传下载

什么是上传和下载?

        数据上传是指客户端向服务器上上传数据,客户端向服务器发送的所有请求都属于数据上传,文件上传是数据上传的一种特例,指客户端从向服务器上传文件。即将保存在客户端的文件上传至服务器中一个副本,保存到服务器中。

        数据下载是指客户端从服务器上获取数据的过程。文件下载就是数据下载的一种特例,指客户端从服务器下载文件,即将原来保存在服务器中的文件下载到客户端中一个副本保存。通常我们对服务器所发出的请求,大多是文件下载请求,从服务器下载文本,图片,声音,视频等文件。然后由客户端浏览器对这些文件进行解析后,才可能看到这些多媒体信息。

        但我们这里说的文件下载,指的是文件从服务器下载到浏览器后,浏览器并不直接解析,而是以附件的形式保存到客户端。

        上传与下载的文件可以是文本文件,图片,声音,视频等各种类型。

文件上传的实现

        文件上传要求客户端表单提交特殊的请求--multipart请求,即包含多部份数据的请求。所以文件表单对于表单数据的编码类型要求,必须为/multipart/form-data,即要为<form/>标签指定enctype属性值为“multipart/form-data”。enctype,即encoding type,编码类型。表单中要有file表单元素。

        由于客户端上传文件的大小是不确定的,所以HTTP协议规定,文件上传的数据要存放于请求正文中,而不能出现在URL的地址栏中,因为地址栏中可以存放的数据量太小。也就是说,文件上传的表单,必须提交POST请求,而不能提交GET请求。

接收并将上传的文本文件显示到网页

 RegisterServlet 

public class RegisterServlet extends HttpServlet {

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 以输出流的形式获取multipart请求的请求体内容
		ServletInputStream is = request.getInputStream();
		// 将输入流中的数据写入到标准输出流中
		PrintWriter out = response.getWriter();
		int len = -1;
		byte[] buffer = new byte[1024];
		while ((len = is.read(buffer)) != -1) {
			String str = new String(buffer, 0, len);
			out.println(str);
		}
		// 关闭输入流
		is.close();
	}
}

文件上传到服务器端后对输入流的解析

通常使用第三方jar包完成,jar包下载,通过apache官网找到PROJECT LIST

commons->FileUpload

 

进入下载想要的版本

在说明中可以看到,还需要下载Commons IO 2.2(或以上版本都可以)

下载导入项目即可。


上传图片并在服务器另存

public class RegisterServlet extends HttpServlet {

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 判断请求是否为multipart请求
		if (!ServletFileUpload.isMultipartContent(request)) {
			throw new RuntimeException("当前请求不支持文件上传");
		}
		try {
			// 创建一个FileItem工厂
			DiskFileItemFactory factory = new DiskFileItemFactory();
			// 创建文件上传核心组件
			ServletFileUpload upload = new ServletFileUpload(factory);
			// 解析请求,获取到所有的items
			List<FileItem> items = upload.parseRequest(request);
			// 遍历item
			for (FileItem item : items) {
				// 判断item是普通表单项还是文件表单项
				if (item.isFormField()) {
					// 获取表单项名称,值
					String fieldName = item.getFieldName();
					String fieldValue = item.getString();
					System.out.println(fieldName + "=" + fieldValue);
				} else {
					// 获取文件表单项文件名,内容
					String fileName = item.getName();
					InputStream is = item.getInputStream();
					// 将文件另存
					String path = this.getServletContext().getRealPath("/images");
					File descFile = new File(path, fileName);
					OutputStream os = new FileOutputStream(descFile);
					int len = -1;
					byte[] buffer = new byte[1024];
					while ((len = is.read(buffer)) != -1) {
						os.write(buffer, 0, len);
					}
					// 关闭流
					os.close();
					is.close();
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		}
	}
}

成功

设置临时文件

客户端向服务器上传文件时,文件在上传时是被分割成了很多数据包,在网络中传输中路径是不同的,到达客户端的顺序是不确定的。此时服务器中就引入了临时文件对其进行接收和临时存储,在接收完之后一次性交给输入流处理。也可以避免文件过大占用太多内存。

上传大于1M的图片,可以在temp文件夹中找到生成的临时文件

 删除临时文件

此时会在文件读取完之后删除临时文件。

解决普通表单项乱码问题

解决文件名相关问题

文件名乱码

相同文件名文件被替换

实现对文件大小的限制的

实现对上传文件目录的管理

这样每天的文件都会保存在单独的文件中。不会出现一个文件夹存放太多文件的现象。

如果还是不够就多建几层文件夹,一天的一个文件夹,放在月份里,月份的放年里。

 

文件上传最终版本

public class RegisterServlet extends HttpServlet {

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 判断请求是否为multipart请求
		if (!ServletFileUpload.isMultipartContent(request)) {
			throw new RuntimeException("当前请求不支持文件上传");
		}
		try {
			// 创建一个FileItem工厂
			DiskFileItemFactory factory = new DiskFileItemFactory();
			// 设置使用临时文件的边界值
			// 大于该值上传文件会先保存在临时文件中,否则写入内存
			factory.setSizeThreshold(1024 * 1024 * 1);// 字节
			// 设置临时文件
			String tempPath = this.getServletContext().getRealPath("/temp");
			System.out.println(tempPath);
			File temp = new File(tempPath);
			factory.setRepository(temp);
			// 创建文件上传核心组件
			ServletFileUpload upload = new ServletFileUpload(factory);
			// 设置每一个item的头部字符编码,解决文件名中文乱码
			upload.setHeaderEncoding("UTF-8");
			// 设置每个上传文件的最大边界值
			upload.setFileSizeMax(1024 * 1024 * 2);
			// 设置一次上传所有文件的总和的最大值
			upload.setSizeMax(1024 * 1024 * 5);
			// 解析请求,获取到所有的items
			List<FileItem> items = upload.parseRequest(request);
			// 遍历item
			for (FileItem item : items) {
				// 判断item是普通表单项还是文件表单项
				if (item.isFormField()) {
					// 获取表单项名称,值
					String fieldName = item.getFieldName();
					String fieldValue = item.getString("UTF-8");
					System.out.println(fieldName + "=" + fieldValue);
				} else {
					// 获取文件表单项文件名,内容
					String fileName = item.getName();// 原始文件名
					fileName = System.currentTimeMillis() + fileName;
					InputStream is = item.getInputStream();
					// 将文件另存
					String path = this.getServletContext().getRealPath("/images");
					// 获取当前系统时间
					Calendar now = Calendar.getInstance();
					int year = now.get(Calendar.YEAR);
					int month = now.get(Calendar.MONTH) + 1;
					int day = now.get(Calendar.DAY_OF_MONTH);
					path = path + "/" + year + "/" + month + "/" + day;
					// 若该目录不存在则创建
					File dirFile = new File(path);
					if (!dirFile.exists())
						dirFile.mkdirs();// 创建多级目录
					File descFile = new File(path, fileName);
					OutputStream os = new FileOutputStream(descFile);
					int len = -1;
					byte[] buffer = new byte[1024];
					while ((len = is.read(buffer)) != -1) {
						os.write(buffer, 0, len);
					}
					// 关闭流
					os.close();
					is.close();

					// 删除临时文件
					item.delete();
				}
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
		}
	}
}

文件下载的实现

超链接方式的文件下载

下载内容的形式由浏览器决定。

对于浏览器能解析的,例如图片,视频等都会直接在浏览器上显示。

Servlet方式的文件下载

public class DownloadServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 文件名
		String fileName = "金币.jpg";
		// 打散,按当前字符编码格式
		byte[] bytes = fileName.getBytes("UTF-8");
		// 组装,按目标字符编码
		fileName = new String(bytes, "ISO8859-1");
		// 修改相应的头部属性content-disposition值为attachment(附件)
		response.setHeader("content-disposition", "attachment;filename=" + fileName);
		// 获取连接服务器端资源文件的输入流
		InputStream is = this.getServletContext().getResourceAsStream("/resources/gold.jpg");
		// 获取输出流
		ServletOutputStream os = response.getOutputStream();
		// 将输入流中内容写入输出流
		int len = -1;
		byte[] buffer = new byte[1024];
		while ((len = is.read(buffer)) != -1) {
			os.write(buffer, 0, len);
		}
		// 关闭流
		os.close();
		is.close();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值