Serlvet笔记一(Servlet基础)
Servlet笔记二(请求和响应)
Servlet笔记三(会话及其会话技术)
Servlet笔记四(JSP技术)
Servlet笔记五(EL表达式和JSTL)
Servlet笔记六(Servlet 高级)
Servlet笔记七(JDBC)
Servlet笔记八(数据库连接池与DBUtils工具)
Servlet笔记九(JSP 开发模型)
Servlet笔记十(文件上传和下载)
- 如何实现文件上传
- 文件上传的相关 API
- FileItem 接口
- DiskFileItemFactory 类
- ServletFileUpload 类
- 实现文件上传
- 文件下载
- 实现文件下载
很多Web应用都为用户提供了文件上传和下载的功能,例如,图片的上传与下载、邮件附件的上传与下载等。
如何实现文件上传要实现 Web 开发中的文件上传功能,通常需完成两步操作:
一 是在 Web 页面中添加上传输入项;
二 是在 Servlet 中读取上传文件的数据,并保存到本地硬盘中。
由于大多数文件的上传都是通过表单的形式提交给服务器的,因此,要想在程序中实现文件上传的功能,首先要创建一个用于提交上传文件的表单页面。在页面中,需要使用 标签在 Web 页面中添加文件上传输入项。
标签的使用需要注意以下两点。
● 必须要设置 input 输入项的 name 属性,否则浏览器将不会发送上传文件的数据。
● 必须将表单页面的 method 属性设置为 post 方式,enctype 属性设置为“multipart/form-data” 类型。
示例代码如下。
<%--指定表单数据的enctype属性以及提交方式--%>
2. 创建 Servlet
UploadServlet.java
package com.xxx.servlet;
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.annotation.WebServlet;
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;
@WebServlet("/UploadServlet")
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
try {
// 创建 DiskFileItemFactory 工厂对象
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置文件缓存目录,如果该目录不存在则新创建一个
File f = new File("/home/sweetheart/Desktop/myjava/temp/");
if(!f.exists()){
f.mkdirs();
}
// 设置文件的缓存目录
factory.setRepository(f);
// 创建 ServletFileUpload 对象
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 设置字符编码
fileUpload.setHeaderEncoding("utf-8");
// 解析 request, 得到上传文件的 FileItem 对象
List fileitems = fileUpload.parseRequest(req);
// 获取字符流
PrintWriter out = resp.getWriter();
// 遍历集合
for (FileItem fileItem: fileitems){
// 判断是否为普通字段
if(fileItem.isFormField()){
// 获取字段名及值
String name = fileItem.getFieldName();
if("name".equals(name)){
if(!fileItem.getString().equals("")){
String value = fileItem.getString("utf-8");
out.println("上传者:" + value + "
");
}else{
System.out.println("上传者的信息是空的");
}
}
}else{ // 上传的是文件
// 获取文件名
String filename = fileItem.getName();
if(filename != null && !"".equals(filename)){
out.println("上传的文件名称为:" + filename + "
");
// 截取文件名,将带有客户端文件路径的前缀部分进行删除
filename = filename.substring(filename.lastIndexOf("/") + 1);
// 设置文件名唯一
filename = UUID.randomUUID().toString() + "_" + filename;
// 在服务创建同名的文件
String webPath = "/upload/";
// 将服务器中文件夹路径与文件名组合成完整的服务器路径(绝对路径)
String filepath = getServletContext().getRealPath(webPath + filename);
// 创建文件
File file = new File(filepath);
file.getParentFile().mkdirs();
file.createNewFile();
// 获取上传文件的输入流
InputStream ins = fileItem.getInputStream();
// 使用 FileOutputStream 打开服务器端上传文件
FileOutputStream fos = new FileOutputStream(file);
// 使用流写入文件中
byte[] buffer = new byte[1024]; // 1k 字节
int len;
// 循环写入
while ((len = ins.read(buffer)) > 0){
fos.write(buffer, 0, len);
}
// 关闭流
fos.close();
ins.close();
// 删除临时文件
fileItem.delete();
out.println("上传文件成功!
");
}else{
System.out.println("没有上传");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3. 运行结果
存放的临时文件被删除
实现文件下载功能比较简单,通常情况下,不需要使用第三方组件实现,而是直接使用 Servlet 类和输入/输出流实现。与访问服务器文件不同的是,要实现文件的下载,不仅需要指定文件的路径,还需要在 HTTP 协议中设置两个响应消息头:
// 设定接收程序处理数据的方式 Content-Disposition: attachment;filename= // 设定实体内容的 MIME 类型 Content-Type: application/x-msdownload
浏览器通常会直接处理响应的实体内容,需要在 HTTP 响应消息中设置两个响应消息头字段,用来指定接收程序处理数据内容的方式为下载方式。当单击 [下载] 超链接时,系统将请求提交到对应的 Servlet。在该 Servlet 中,首先获取下载文件的地址,并根据该地址创建文件字节输入流,然后通过该流读取下载的文件内容,最后将读取的内容通过输出流写到目标文件中。
实现文件下载项目结构
1. 创建下载页面
download.jsp
<%@ page import="java.net.URLEncoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
">文件下载
2. 创建 Servlet
DownloadServlet.java
package com.xxx.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@WebServlet("/DownloadServlet")
public class DownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置编码
resp.setContentType("text/html;charset=utf-8");
// 获取下载文件名
String filename = req.getParameter("filename");
// 解决中文编码问题
filename = new String(filename.getBytes(StandardCharsets.UTF_8));
// 下载文件所在文件夹
String folder = "/download/";
// 通知浏览器以下载方式打开; encode编码器 解决中文编码
resp.addHeader("Content-Type", "application/octet-stream");
resp.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "utf-8"));
// 获取输入流
InputStream ins = getServletContext().getResourceAsStream(folder+filename);
// 获取 response 对象的输出流
OutputStream out = resp.getOutputStream();
// 1k字节
byte[] buffer = new byte[1024];
int len;
// 循环输出
while ((len=ins.read(buffer)) != -1){
out.write(buffer, 0, len);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
EncodingFilter.java
package com.xxx.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/DownloadServlet")
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
chain.doFilter(request, response);
}
@Override
public void destroy() {
System.out.println("destroy...");
}
}
3. 创建下载目录及文件
4. 运行结果



