文件的上传的概念了解
文件上传
操作
- 在web页面上添加传输入项
- 在Servlet中读取上传文件的数据,并保存到(服务器)本地硬盘中。
表单形式的上传文件
- 在 中name必须有,否则浏览器不会上传文件的数据。
- 表单的方法method=”post“,enctype=”multipart/form-data“类型
- 默认的enctype不会上传文件的数据,只会上传文件的名称。
- 通过表单将表单中的数据存放到Http的消息请求体中,并且通过MIME类型进行描述,在Servlet可以通过采用request.getInputStream()方法读取到客户段发送来的数据,但是在Servlet中读取并且解析相应文件是相当的麻烦的。所以提供了一个开源组件Commons-FileUpload。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="#" method="post " enctype="multipart/form-data">
上传文件:<input type="file" name="filName"><br>
登录:<input type="submit" value="登录">
</form>
</body>
</html>
FileItem接口
用于封装单个表单字段元素的数据。
- isFormField() 判断FileItem对象封装的是否是一个普通文本表单字段 ;
- String getName() 获取文件的上传字段的文件名
- String getFieldName() : 获取表单字段描述头的name的属性值
- void write(File file) : 将FileItem对象保存到指定的文件中,
- String getString(): 将FileItem对象中保存的数据流内容以一个字符串返回,
- String getContentType() : 获取上传文件的类型
- Boolean isInMemory() : 判断FileItem对象封装的数据内容存储在内存中,还是在临时的内存中。
- void delete() 清空FileItem中存放的内容
- inputStream getInputStream() 以流的形式返回上传文件的数据内容
- long getSize() : 返回上传文件的大小(字节为单位)
DiskFileItemFactory
- 将消息体中的每个文件封装成单独FileItem对象,文件小,存到内存中,文件大,以临时文件存储。
- 它的构造方法
- DiskFileItemFactory() : 采用默认的临界值和系统临时文件夹构造文件工厂对象。
- DiskFileItemFactory(int size Threshold,File repository) : 采用设定的临界值和系统临时文件夹构造文件工厂对象。
- 它的方法
- FileItem createItem(String fieldName,String contentType, boolean isFormField,String fileName);
- setSizeThreshold(int sizethreshold) 和getSizeThreshold()
- setRepository(File repository) 和get Repository.
ServletFileUpload
处理文件上传的核心类
- 构造方法
- ServletFileUpload():方法构造一个未初始化的实例对象
- ServletFileUpload (FileItemFactory fileItemFactory) 根据指定参数的FileItemFactory对象创建一个ServeltFileUpload对象,
- 方法
- setSizeMax(long sizeMax) 和getSizeMax()方法: 用于设置请求消息实体内容的最大限制
- parseRequest(): 对Http请求消息体内容进行解析入口,解释出form表单中每个字段的数据,并封装成FileItem对象中,将对象加入到list集合中。
- setFileSizeMax()和getFileSizeMax()
- getItemIterator():迭代器,保存时FileItemStream对象
- isMultiparContent: 是消息体内容是否是”multipart/form-data“类型
- getFileItemFactory()
- setHeaderEncoding(): 用于设置读取和设置编码
实现文件上传
- 过程
- 导入Jar包
- 准备上传网页,form.jsp
- 处理请求的Servlet
form.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="UploadServlet" method="post" enctype="multipart/form-data">
<%--上传文件:<input type="file" name="filName"><br>--%>
<%--登录:<input type="submit" value="登录">--%>
<table width="600px">
<tr>
<td>上传者</td>
<td>
<input type="text" name="name">
</td>
</tr>
<tr>
<td>上传文件</td>
<td>
<input type="file" name="myfile">
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="上传">
</td>
</tr>
</table>
</form>
</body>
</html>
UploadServlet
package com.yue;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;
public class UploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
//设置ContentType的值
resp.setContentType("text/html;charset=utf-8");
//创建DiskFileItemFactory工厂对象
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//设置文件缓存目录,如果目录不存在就新建一个
File file = new File("E:\\new");
if (!file.exists()) {
file.mkdirs();
}
//设置缓存路径
diskFileItemFactory.setRepository(file);
//创建ServletFileUpload对象
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
//设置字符编码
servletFileUpload.setHeaderEncoding("utf-8");
//解析request,得到上传文件FileItem对象
List<FileItem> fileItems = servletFileUpload.parseRequest(req);
//获取字符流
PrintWriter writer = resp.getWriter();
//遍历集合
for (FileItem fileItem : fileItems) {
//判断是否是普通字段
if (fileItem.isFormField()) {
//获得字段名和字段值
String name = fileItem.getFieldName();
if (name.equals("name")) {
//如果文件不为空,将其保存在value中
if (!fileItem.getString().equals("")) {
String value = fileItem.getString("utf-8");
writer.print("上传者:" + value + "<br/>");
}
}
}else {
//获取上传的文件名
String name = fileItem.getName();
if(name != null && !name.equals("")){
writer.print("上传者文件名称是:" +name + "<br/>");
}
//截取出文件名
name = name.substring(name.lastIndexOf("\\") + 1);
//文件名需要唯一性
name = UUID.randomUUID().toString() + "_" + name;
//在服务器创建同名文件
String webPath = "/upload";
//将服务器中文件加路径域文件名组合成完整的服务器端路径
String realPath = getServletContext().getRealPath(webPath + name);
//创建文件
File file1 = new File(realPath);
file1.getParentFile().mkdirs();
file1.createNewFile();
//获得上传文件流
InputStream inputStream = fileItem.getInputStream();
//使用FileoutputStream打开服务器端上传文件
FileOutputStream fileOutputStream = new FileOutputStream(file1);
//流的拷贝
byte[] bytes = new byte[1024];//每次读取一个字节
int len;
//开始读取上传文件的字节,并将其输出到服务器的上传文件输出流中
while((len = inputStream.read(bytes))>0){
fileOutputStream.write(bytes,0,len);
//关闭流
inputStream.close();
fileOutputStream.close();
//删除临时文件
fileItem.delete();
writer.print("上传文件成功!<br/>");
}
}
}
}catch (Exception e){
throw new RuntimeException(e);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
文件的下载
文件的下载:从服务器端把文件保存到本地
文件的下载:一个流两个头
>>> 一个流:文件的字节输入流
>>> 两个头(相应头):
Content-Type:对应文件的MIME的类型,可以理解为文件的扩展名
Content-Dispostion:以下载框的方式保存文件。
download.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="/chapter12/DownloadServlet?filename=1.jpg">下载文件</a>
</body>
</html>
DownLoadServlet
package com.yue;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码问题
resp.setContentType("text/html;charset=utf-8");
//获取下载文件的名称,在这里可以使用req和resp,这里的下载的servletfileupload和上传的没有关系。
String filename = req.getParameter("filename");
// String filename = "1.jpg";
//获取文件的类型
// String mimeType = getServletContext().getMimeType(filename);
//通知浏览器以下载的方式打开
resp.setHeader("Content-Type","application/octet-stream");
resp.setHeader("Content-Disposition","attachment;filename="+filename);
String folder ="/download";
//获取文件的字节输入流
InputStream resourceAsStream = getServletContext().getResourceAsStream(folder + filename);
//获取文件的字节输出流
ServletOutputStream outputStream = resp.getOutputStream();
byte[] bytes = new byte[1024];
int len;
while((len = resourceAsStream.read(bytes) )!=-1){
outputStream.write(bytes,0,len);
}
outputStream.close();
resourceAsStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
解决上传文件名中文乱码问题
方式一
在download.jsp
<a href="/chapter12/DownloadServlet?filename=<%=URLEncoder.encode(“风景.jpg”, “utf-8”)%>">下载文件是中文1
在DownloadServlet
resp.setHeader(“Content-Disposition”,“attachment;filename=”+ URLEncoder.encode(filename,“utf-8”));
只在IE浏览器中有效
方式二
添加一个工具类
DownUtils
根据浏览器的不同,进行不同的编码
package com.yue;
import sun.misc.BASE64Encoder;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class DownUtils {
public static String filenameEncoding(String filename, HttpServletRequest request) throws UnsupportedEncodingException {
// 获得请求头中的User-Agent
String agent = request.getHeader("User-Agent");
// 根据不同的客户端进行不同的编码
if (agent.contains("MSIE")) {
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else if (agent.contains("Firefox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
DownloadServlet
package com.yue;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//解决中文乱码问题
resp.setContentType("text/html;charset=utf-8");
//获取下载文件的名称,在这里可以使用req和resp,这里的下载的servletfileupload和上传的没有关系。
String filename = req.getParameter("filename");
// String filename = "1.jpg";
//获取文件的类型
// String mimeType = getServletContext().getMimeType(filename);
//通知浏览器以下载的方式打开
resp.setHeader("Content-Type","application/octet-stream");
resp.setHeader("Content-Disposition","attachment;filename="+filename);
//中文方式1
// resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
//中文方式2
// filename = DownUtils.filenameEncoding(filename, req);
// resp.setHeader("Content-Disposition","attachment;filename="+filename);
String folder ="/download";
//获取文件的字节输入流
InputStream resourceAsStream = getServletContext().getResourceAsStream(folder + filename);
//获取文件的字节输出流
ServletOutputStream outputStream = resp.getOutputStream();
byte[] bytes = new byte[1024];
int len;
while((len = resourceAsStream.read(bytes) )!=-1){
outputStream.write(bytes,0,len);
}
outputStream.close();
resourceAsStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
download.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@page import="java.net.URLEncoder"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="/chapter12/DownloadServlet?filename=1.jpg">下载文件</a>
<br/>
<a href="/chapter12/DownloadServlet?filename=<%=URLEncoder.encode("风景.jpg", "utf-8")%>">下载文件是中文1</a>
<br>
<a href="/chapter12/DownloadServlet?filename=风景.jpg">下载文件是中文2</a>
</body>
</html>