随着Web技术的发展,处理文件资源成为每个Web应用的标配功能,其中最常用的是文件的上传和下载。在日常生活中,人们往往会在不经意间使用这些功能,例如,把一张照片上传到服务器、把邮箱中的附件下载到本地磁盘等。文件上传是Web应用程序中的常见操作,简单来说,他指的是将本地文件通过数据流上传到服务器端的某一个特定的目录下。
在Java Web开发中,文件上传通常按照固定的流程进行。表单页面->浏览器编码->服务器解码、保存。文件上传要经过表单页面、浏览器和服务器三个环节。首先,浏览器提供给用户一个包含文件上传元素的表单页面,用户选择提交内容后提交请求,文件数据和其他表单信息被浏览器编码并上传至服务器端,服务器端解码上传的内容,提取出HTML表单中的信息,然后将文件数据存入磁盘。
Servlet3.0之前:需要使用一个第三方库:Apache Commons Fileupload
Servlet3.0之后:依然可以添加依赖,而且增加了 Servlet 自带的文件上传方案
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
/**
* 处理文件上传的接口
*/
@WebServlet(urlPatterns = "/fileupload")
//开启文件上传功能
/**
* location:临时的文件保存位置
* maxFileSize: 上传的文件最大的大小
* maxRequestSize: 最大的请求大小
* fileSizeThreshold: 向磁盘保存的临界值
*/
@MultipartConfig(location = "E:\\tmp")
public class FileUpload extends HttpServlet{
private SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
/**
* 上传的文件放在请求体中,所以需要在 doPost 中处理文件上传
*
* 一个文件上传请求,除了携带文件,也可以携带其他普通参数
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//普通参数的获取
String username = req.getParameter("username");
//获取上传的文件对象
Part file = req.getPart("file");
//将文件保存到当前项目运行的目录下
//获取项目运行的根目录
String rootFolder = req.getServletContext().getRealPath("/");
String format = sdf.format(new Date());
String realPath = rootFolder + "/img" + format;
File folder = new File(realPath);
if(!folder.exists()){
folder.mkdirs();
}
//获取旧的文件名
String submittedFileName = file.getSubmittedFileName();
//获取文件后缀 最后 . 开始截取
String suffix = submittedFileName.substring(submittedFileName.lastIndexOf("."));
//新的文件名
String newName = UUID.randomUUID().toString() + suffix;
//文件保存
file.write(realPath + newName);
//接下来生成文件访问路径,并保存到数据库中
//获取请求协议
String url = req.getScheme() + "://" +
//获取服务名(域名)
req.getServerName() + ":"
//获取项目端口号
+ req.getServerPort()
//获取项目名
+ req.getContextPath() + "/img" + format + newName;
resp.getWriter().write(url);
}
}
下面使用表单页面提交post请求方法和ajax发送请求的方法来获取需要上传的文件。
enctype属性设置为multipart/form-data。multipart/form-data是一种编码方式,他会使用分界符将数据流中的数据段分开,从而帮助服务器端识别文件内容。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="/f/fileupload" method="post" enctype="multipart/form-data">
<input type="text" name="username">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="jquery.min.js"></script>
</head>
<body>
<div>
<input type="text" id="username">
<input type="file" id="file">
<input type="button" value="上传" onclick="uploadFile()">
</div>
<div id="result"></div>
<script>
function uploadFile() {
let username = $("#username").val();
//查找到 file 对象,将其转为 js 对象,然后调用 js 对象中的 files 属性,该属性中保存了 input 选中的所有文件,我们这里时单选,所以选择数组的第一项即可
let file = $("#file")[0].files[0];
//构建 data 对象,这个对象就是将来上传文件时候的对象
let data = new FormData();
data.append("username", username);
data.append("file", file);
$.ajax({
type: 'post',
url: '/f/fileupload',
data:data,
contentType: false,
processData: false,//本来参数会进行预处理,但是现在是文件上传,参数不需要预处理
success:function (msg) {
$("#result").html(msg);
}
})
}
</script>
</body>
</html>
以上即为Servlet继承Http类文件上传功能的代码。
|