JavaWeb 文件上传与下载(一)
文件的上传和下载,是非常常见的功能。很多的系统中,或者软件中都经常使用文件的上传和下载。
比如:用户头像上传、 邮箱中附件的上传与下载以及OA 系统中审批有附件材料的上传。
Http协议说明
请求头部:Content-Type: multipart/form-data; boundary=----WebKitFormBoundary10MOHr9k7lABzMdB
Content-Type
:表示提交的数据类型。
multipart/form-data;
:表示提交的数据,以多段(每一表单项为一个数据段)的形式进行拼接,然后以二进制流发送个服务器。
boundary
:表示每段数据的分隔符----WebKitFormBoundary10MOHr9k7lABzMdB
(浏览器自动生成)它是没段数据的分界符。
引入commons-fileupload.jar与commons-io.jar包
要使用commons-fileupload.jar
包还需要引入commons-io.jar
常用API说明:
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)
:将上传到文件写到参数file
所指向磁盘位置。
创建JSP页面
<form action="http://localhost:8000/upload/upLoadServlet" method="post" enctype="multipart/form-data">
用户名:<input name="username" type="text" ><br>
用户头像:<input name="photo" type="file"><br>
<input type="submit" value="提交">
</form>
创建UpLoadServlet类
public class UpLoadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
/* 服务器如何接受上传数 */
//1.先判断上传的数据是否多段数据(只有是多端数据,才是文件上传的)
if (ServletFileUpload.isMultipartContent(req)) {
// 1.1创建FileItemFactory工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 1.2创建ServletFileUpload解析上传文件的工具类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
// 1.3调用parseRequest解析方法,得到每一个表单项FileItem
try {
List<FileItem> list = servletFileUpload.parseRequest(req);
for (FileItem item : list) {
if (item.isFormField()){
// 普通表单项
System.out.println("表单项的name属性值:" + item.getFieldName());
// 参数UTF-8解决乱码问题
System.out.println("表单项的value属性值:" + item.getString("UTF-8"));
} else {
// 上传的文件
System.out.println("表单项的name属性值:" + item.getFieldName());
System.out.println("上传的文件名:" + item.getName());
// 写入到磁盘路径
item.write(new File("F:\\img\\" + item.getName() ));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
配置web.xml文件
<servlet>
<servlet-name>UpLoadServlet</servlet-name>
<servlet-class>com.servlet.upload.UpLoadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UpLoadServlet</servlet-name>
<url-pattern>/upLoadServlet</url-pattern>
</servlet-mapping>
文件下载
resp.setHeader(“Content-Disposition”,“attachment;filename=a.png”);
ontent-Disposition
响应头,表示收到的数据怎末处理。
attachment
:表示附件,下载使用。
filename=文件名称
表示下载的文件名。
如果在下载是文件名中文,则无妨正常显示中文名称,原因是响应头中只能包含ASCLL码。这是我们需要使用UTLEncod.encode
来处理中文名称无法识别。
例如:resp.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("图片.png","UTF-8"));
而针对于火狐浏览器我们可以使用Base64编码
Base64
响应头格式:filename==?charset?B?文件名?="
=?
:开头。
charset
:字符集。
B
:Base64。
?=
:结尾。
例如:resp.setHeader("Content-Disposition", "attachment;filename==?UTF-8?B?" + new BASE64Encoder().encode("图片.png".getBytes("UTF-8")) + "?=");
创建Download类
public class Download extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1.获取要下载的文件名
String downloadFileName = "slider-4.png";
// 2.通过ServletContext对象处理
ServletContext servletContext = getServletContext();
// 3.在回传前,通过响应头告诉客户端所返回的数据类型
String mimeType = servletContext.getMimeType("/file/" + downloadFileName);
System.out.println("文件类型:" + mimeType);
resp.setContentType(mimeType);
// 3.1 告诉客户端所接受到的数据是用于下载的,并判断客户端浏览器是否为火狐
if (req.getHeader("User-Agent").contains("Firefox")) {
// 如果是火狐浏览器,则使用Base64编码
resp.setHeader("Content-Disposition", "attachment;filename==?UTF-8?B?" + new BASE64Encoder().encode("图片.png".getBytes("UTF-8")) + "?=");
} else {
// 而其他浏览器,则使用URLEncode编码
resp.setHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode("图片.png","UTF-8"));
}
// 4.获取要下载的文件
InputStream resourceAsStream = servletContext.getResourceAsStream("/file/" + downloadFileName);
// 5.1获取响应输出流
ServletOutputStream outputStream = resp.getOutputStream();
// 6.读取输入流中全部的数据,赋值给输出流,并输出个前端
IOUtils.copy(resourceAsStream,outputStream);
}
}
配置web.xml文件
<servlet>
<servlet-name>Download</servlet-name>
<servlet-class>com.tuoyingtao.servlet.Download</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Download</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>