文件的上传和下载是非常常见的功能:比如QQ的头像上传,OA系统中审批有附件材料的上传...
文件上传的前提:
- 有form标签,method=post 请求【Get请求有限制长度】。
- form标签中,enctype="multipart/form-data",这个属性值必须固定,不能变。
- 在form标签中使用 input type=file 进行上传
- 在服务器端编写代码,用来接收文件并进行 处理
<form enctype="multipart/form-data" action="/jsp_01/onload" method="post">
用户名:<input type="text" name="userName"><br>
头像上传:<input type="file" name="file"><br>
<input type="submit" value="提交">
</form>
enctype="multipart/form-data" : 表示提交的数据,以多段(每一个表单项一个数据段)的形式进行拼凑,然后以二进制流的形式发送给服务器。
请求协议介绍:
上传文件的步骤:
将 commons-fileupload.jar 和 commons-io.jar 这俩个包导入
commons-fileupload.jar 和 和 commons-io.jar 包中,我们常用的类有哪些?
- ServletFileUpload 类,用于解析上传的数据。
- FileItem 类,表示每一个表单项。
- boolean ServletFileUpload.isMultipartContent(HttpServletRequest request);
- 判断当前上传的数据格式是否是多段的格式。
- public List<FileItem> parseRequest(HttpServletRequest request)
- 解析上传的数据
- boolean FileItem.isFormField()
- 判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。
- true 表示普通类型的表单项
- false 表示上传的文件类型
- 判断当前这个表单项,是否是普通的表单项。还是上传的文件类型。
- String FileItem.getFieldName()
- 获取表单项的 name 属性值
- String FileItem.getString()
- 获取当前表单项的值。
- String FileItem.getName();
- 获取上传的文件名
- void FileItem.write( file );
- 将上传的文件写到 参数 file 所指向抽硬盘位置 。
public class OnloadServlet extends HttpServlet {
@Override
/*处理文件上传的Servlet*/
// 文件是以流的方式上传的,在这里接受也必须是流的方式
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 防止出现乱码问题
request.setCharacterEncoding("UTF-8");
//判断上传的数据是否是以多段数据,只有多段数据的,才是文件上传的。
if(ServletFileUpload.isMultipartContent(request)){
//创建FileItemFactory工厂类
FileItemFactory itemFactory = new DiskFileItemFactory();
//创建用于解析上传数据的工具类 ServletFileUpload
ServletFileUpload upload = new ServletFileUpload(itemFactory);
try {
//解析上传的数据,每一个表单向都是 FileItem 类型
List<FileItem> list = upload.parseRequest(request);
for (FileItem fileItem:list) {
//判断每一个表单项的类型,普通文本和文件的处理方式是不一样的
if (fileItem.isFormField()){
/*是一个普通文本*/
System.out.println("表单项的name属性值:" + fileItem.getFieldName());
//参数 UTF-8 解决乱码问题
System.out.println("表单项的value属性值:" + fileItem.getString("UTF-8"));
}else{
/*文件类型*/
System.out.println("表单项的name属性值:" + fileItem.getFieldName());
System.out.println("上传的文件名:" + fileItem.getName());
fileItem.write(new File("C:\\web后端\\"+fileItem.getName()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
下载文件的步骤:
下载需要使用的方法:
- 第一步:获取ServletContext对象
- ServletContext context = this.getServletContext
- 第二步:获取下载文件的类型
- String MimeType = context.getMimeType("文件路径");
- 第三步:通知客户端返回的数据类型
- response.setContentType(MimeType );
- 第四步:表名该文件是用于下载的
- response.setHeader("Content-Disposition", "attachment; fileName=1.jpg");
- 这个响应头告诉浏览器。这是需要下载的。而 attachment 表示附件,也就是下载的一个文件。fileName=后面,表示下载的文件名。
- 第五步:获取输入流
- InputStream input = context.getRecourceAsStream("文件路径")
- 第六步:获取输出流
- ServletOutputStream output = response.getOutputStream();
- 第七部:复制
- IOUtils.copy(input,output);
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
/*读取下载的文件内容【通过ServletContext对象可以读取】*/
ServletContext context = this.getServletContext();
/*获取下载文件的类型*/
String mimeType = context.getMimeType("/file/1.jpg");
System.out.println(mimeType);
/*告诉客户端返回的数据类型*/
resp.setContentType(mimeType);
/*告诉客户端收到的数据是用于下载的*/
resp.setHeader("Content-Disposition", "attachment; fileName=1.jpg");
// / 表示从web根目录下开始查找。
InputStream inputStream = context.getResourceAsStream("/file/1.jpg");
/*获取输出流*/
ServletOutputStream outputStream = resp.getOutputStream();
IOUtils.copy(inputStream,outputStream);
}
}
需要注意的是:
如果文件名是中文的,会出现乱码问题,浏览器解析不了,下载不了了。
在下载时需要设置字符编码集:
response.setHeader("Content-Disposition", "attachment; fileName="+ URLEncoder.encode("中文.jpg", "UTF-8"));
URLEncoder.encode("中文.jpg", "UTF-8") ,这种方式IE,谷歌,火狐也支持了。
"中文.jpg":文件名 "UTF-8" :编码集