JavaWeb学习笔记——文件上传与下载

文件上传

要求

  1. 准备一个 form 表单,method=post
  2. form 标签的 encType 属性值必须为 multipart/form-data
  3. 在表单内使用 input type=file 添加上传的文件
  4. 编写 Servlet 程序接收请求,处理上传的数据。

encType=multipart/form-data 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器。

commons-fileupload.jar

文件上传需要导入两个包:commons-fileupload.jar、commons-io.jar

意义
ServletFileUpload 类用于解析上传的数据
FileItem 类表示每一个表单项
ServletFileUpload 类内的方法意义
static boolean isMultipartContent(HttpServletRequest req)判断当前上传的数据格式是否为多段的格式
public List<FileItem> parseRequest(HttpServletRequest request)解析上传的数据
FileItem 类内的方法意义
boolean isFormField()判断当前的表单项是普通的表单项,还是上传文件项,true 表示普通类型的表单项,false 表示上传文件
String getFieldName()获取表单项的 name 属性值
String getString()获取表单项的 value 属性值
String getName()获取上传文件的文件名
void write(file)将上传的文件写入参数 file 所指向的磁盘路径

实现

upload.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- 
		文件上传:
		1、要有一个 form 标签,method=post 请求
		2、form 标签的 encType 属性值必须为 multipart/form-data 值
		3、在 form 标签中使用 input type=file 添加上传的文件
		4、编写服务器代码(Servlet 程序)接收,处理上传的数据。
	 -->
	<form action="http://localhost:8080/jspWeb/uploadServlet" method="post" enctype="multipart/form-data">
		<!-- 普通表单项 -->
		用户名:<input type="text" name="username"><br>
		<!-- 上传文件项 -->
		<input type="file" name="photo"><br>
		<input type="submit" value="上传">
	</form>
</body>
</html>

UploadServlet.java

package servlet;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
 * ServletFileUpload类:用于解析上传的数据
 * 		boolean ServletFileUpload.isMultipartContent(HttpServletRequest request) 判断当前上传的数据格式是否是多段的格式。
 * 		List<FileItem> parseRequest(HttpServletRequest request)	解析上传的数据
 *	
 * FileItem类:表单项类
 * 		boolean isFormField()	判断当前这个表单项,是普通的表单项,还是上传的文件类型
 * 			true 表示普通类型的表单项
 * 			false 表示上传的文件类型
 * 		String getFieldName()	获取表单项的name属性的值
 * 		String getString()	获取当前表单项的value值
 * 		String getName()	获取上传文件的文件名
 * 		void FileItem.write(File file)	将上传的文件写到file所指向的硬盘位置 
 * @author MCC
 *
 */
public class UploadServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//1.判断提交的数据是否是多段数据,只有是多段数据才可能是上传的数据
		if(ServletFileUpload.isMultipartContent(req)) {
			//如果为true,代表是多段数据
			//2.创建fileItemFactory接口实现类
			FileItemFactory fileItemFactory = new DiskFileItemFactory();
			//3.创建ServletFileUpload对象,以供解析上传的数据
			ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
			//4.解析数据
			try {
				List<FileItem> list = servletFileUpload.parseRequest(req);
				//遍历list集合,对于普通表单项与上传的文件表单项进行不同的操作
				for(FileItem item : list) {
					if(item.isFormField()) {
						//返回true代表item是普通表单项
						System.out.println("表单项的name属性值:" + item.getFieldName());
						System.out.println("表单项的value属性值:" + item.getString("UTF-8"));
					} else {
						//返回false代表item是上传数据的表单项
						System.out.println("表单项的name属性值:" + item.getFieldName());
						System.out.println("上传的文件名:" + item.getName());
						//保存上传的文件
						item.write(new File("C:\\Users\\MCC\\Desktop\\fileUpload\\" + item.getName()));
					}
				}
			} catch (FileUploadException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			//如果为false,代表不是多段数据
			//...
		}
	}
}

文件下载

在这里插入图片描述

步骤

  1. 获取请求下载的资源名,这里假设为固定名称
  2. 获取资源类型,并将该类型告知浏览器
  3. 告诉浏览器该文件是用于下载的,不要直接显示在浏览器中
  4. 读取源文件
  5. 获取响应流
  6. 通过commons.io包下的工具类完成从输入流写入到输出流的工作

API 说明

ServletContext 类: 通过 getServletContext() 或 getServletConfig().getServletContext() 获取

方法意义
getMimeType(String path)获取文件的类型
getResourceAsStream(String path)加载文件

Response类:

方法意义
setContentType(String type)设置响应数据的类型
setHeader(“Content-Disposition”,“attachment; filename=”+“name”)设置响应数据的处理方式

其中,

  • Content-Disposition:表示处理方式
  • attachment:表示附件方式,用于下载
  • filename=:设置下载时的文件名

common.io包:

方法意义
IOUtils.copy(inputStream input, outputStream output)将输入流中的数据复制到输出流中

解决中文乱码问题

  1. URL编码
方法意义
URLEncoder.encode(String chineseName, Charset charset);将中文字符设置为URL编码,解决下载中文文件乱码问题
  1. Base64编码:火狐(fireFox)浏览器
方法意义
Encoder encoder = Base64.getEncoder();获取base64编码器
encoder.encode(byte[] b);编码
Decoder decoder = Base64.getDecoder();获取base64解码器
encoder.decode(byte[] b);解码

加载文件时的注意事项

要使用如下代码加载源文件:

ServletContext context = getServletContext();
InputStream in = context.getResourceAsStream(String path);

不能使用如下代码加载源文件:

InputStream inputStream = DownloadServlet.class.getResourceAsStream(downloadFileName);

原因:不能用类的加载器加载文件,因为服务器解析地址时默认是在 http://localhost:8080/工程路径,对应工程的 WebContent 目录进行查找,而类的加载器默认是在 Java 工程目录下进行查找的,java 目录在 web 项目中是隐藏的,不能访问(访问Java文件时要配置 web.xml 文件)

实现

package servlet;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.Base64;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;

public class DownloadServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	/**
	 * 接收下载请求
	 * 
	 * ServletContext类:
	 * 		getMimeType(String path)	获取文件的类型
	 * 		getResourceAsStream(String path)	加载文件
	 * Response类:
	 * 		setContentType(String type)	设置响应数据的类型
	 * 		setHeader("Content-Disposition", "attachment; filename="+"name")	设置响应数据的处理方式
	 * 			Content-Disposition	处理方式
	 * 			attachment	附件方式,用于下载
	 * 			filename=	设置下载时的文件名
	 * common.io包:
	 * 		IOUtils.copy(inputStream input, outputStream output)	将输入流中的数据复制到输出流中
	 * 
	 * URL编码:
	 * 		URLEncoder.encode(String chineseName, Charset charset);	将中文字符设置为URL编码,解决下载中文文件乱码问题
	 * Base64编码:火狐浏览器使用
	 * 		Encoder encoder = Base64.getEncoder();	获取base64编码器
	 * 		encoder.encode(byte[] b);	编码
	 * 		Decoder decoder = Base64.getDecoder();	获取base64解码器
	 * 		encoder.decode(byte[] b);	解码
	 * 
	 *	InputStream inputStream = DownloadServlet.class.getResourceAsStream(downloadFileName);
	 *不能用类的加载器加载文件,因为服务器解析地址时默认是在http://localhost:8080/工程路径	对应工程的WebContent目录进行查找
	 *而类的加载器默认是在Java工程目录下进行查找的,java目录在web项目中是隐藏的,不能访问(访问Java文件时要配置web.xml文件)
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//1.获取请求下载的资源名,这里假设为固定名称
		String downloadFileName = "/2020-11-24_215804.png";
		//2.获取资源类型,并将该类型告知浏览器
		ServletContext context = getServletContext();
		String mimeType = context.getMimeType(downloadFileName);
		resp.setContentType(mimeType);
		//3.告诉浏览器该文件是用于下载的,不要直接显示在浏览器中
		if(req.getHeader("User-Agent").contains("fireFox")) {//如果使用的是火狐浏览器,则使用Base64编码
			resp.setHeader("Content-Disposition", "attachment; filename="
							+ Base64.getEncoder().encode("张大仙.png".getBytes()));
		} else {//如果是其他浏览器,则使用URL编码	
//		resp.setHeader("Content-Disposition", "attachment; filename="+System.currentTimeMillis()+".png");
			resp.setHeader("Content-Disposition", "attachment; filename="
							+ URLEncoder.encode("张大仙.png", "UTF-8"));
		}
		//4.读取源文件
		InputStream inputStream = context.getResourceAsStream(downloadFileName);
		//5.获取响应流
		ServletOutputStream outputStream = resp.getOutputStream();
		//6.通过commons.io包下的工具类完成从输入流写入到输出流的工作
		IOUtils.copy(inputStream, outputStream);
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值