跟着书上的例子写了个文件上传的简单页面,感觉还蛮有意思的
前端
要上传文件,必须利用multipart/form-data设置HTML表单的enctype属性。
<form action="action" method="post" enctype="multipart/form-data">
Select a file <input type="file" name="fieldName" /> 这个fieldName必须设置
服务器端
通过MultipartConfig注解类型和javax.servlet.http.Part接口进行处理,处理上传文件的Servlet必须用@MultipartConfig进行标注
MultipartConfig有以下可选属性
- maxFileSize,表示最多可上传的文件容量,默认值-1。
- maxRequestSize,表示允许多部分HTTP请求的最大容量,默认值为-1
- location,指定上传的文件保存到磁盘中的指定位置
- fileSizeThreshold,设定一个溢出尺寸,超过这个值的文件将被临时存储在磁盘
HttpServletRequest 接口定义了以下方法来处理多部分的请求
- Part getPart(String name),返回与指定名称相关的Part,这个name与前端页面中input的name相同。
- Collection<Part> getParts(),返回所有Part
- String getContentType(),如果Part是一个文件,返回Part的内容类型,否则返回null
- Collection<String> getHeaderNames(),返回这个Part中的所有header名称
- void write(String path),将文件写入指定的路径
- void delete(),删除该文件对应的存储,包括相关的临时文件
- InputStream getInputStream(),以流形式返回上传文件的内容
域的形式
如果上传域中有一个名为document的note.txt文件时,产生的header
content-type:text/plain
content-disposition:form-data; name="document"; filename="note.txt"
如果是一个非文件的域,Part将只有content-disposition的header
格式:content-disposition:form-data; name="fiedlName"
范例
@WebServlet(urlPatterns = "/singleUpload")
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 3, maxFileSize = 1024 * 1024 * 10)
public class UploadFileServlet extends HttpServlet {
private static final long serialVersionUID = 8593039L;
/**
* 从Part中提取文件名
* @param part
* @return
*/
private String getFileName(Part part) {
String contentDispositionHeader = part.getHeader("content-disposition");
String[] elements = contentDispositionHeader.split(";");
for (String element : elements) {
if (element.trim().startsWith("filename")) {
return element.substring(element.indexOf('=') + 1).trim().replace("\"", "");
}
}
return null;
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Part part = req.getPart("filename");
String filename = getFileName(part);
if (filename != null && !filename.isEmpty()) { //检测文件名是否合法
// 在WEB-INF目录下创建/tmp/upload/文件夹,将上传文件存储到这个文件夹下
// WEB-INF目录下的文件是无法通过链接直接访问的
File f = new File(getServletContext().getRealPath("/WEB-INF") + "/tmp/upload/");
if (!f.exists()) {
f.mkdirs();
}
// 将文件写入
part.write(getServletContext().getRealPath("/WEB-INF") + "/tmp/upload/" + filename);
}
// 返回文件的名字,大小,上传者等信息
resp.setContentType("text/html");
PrintWriter writer = resp.getWriter();
writer.print("<br/>Upload file name: " + filename);
writer.print("<br/>Size: " + part.getSize());
String author = req.getParameter("author");
writer.print("<br/>Author: " + author);
writer.close();
}
}
再来看下前端页面singleUpload.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Select a file to upload</h1>
<form action="singleUpload" enctype="multipart/form-data", method="post">
Author: <input type="text" name="author" /><br/>
<!-- 这里name的值“filename”在获取Part对象时使用 -->
Select file to upload <input type="file" name="filename" /> <br/>
<input type="submit" value="Upload">
</form>
</body>
</html>
点击上传就可以在配置的文件夹下看到自己上传的文件了。
总结
这篇博客只是实现了一个很简单的文件上传,算是给自己的后端之路挖下第一个坑(???)一直感觉后端很高大上,第一次动手写东西果然高大上hhhhh,Android里没怎么使用到的注解啊,文件,IO流都在这里得到了较多使用,很神奇的感觉(手动捂脸)。希望能慢慢学点后端知识吧。