接下来我将详细讲解Java基于Servlet实现文件上传功能的完整攻略。该攻略分为以下几个步骤:
- 在HTML页面中添加文件上传表单
- 编写Servlet来处理文件上传请求
- 使用Apache的文件上传组件来解析文件上传请求
- 保存文件到指定位置并返回上传结果给用户
下面就来详细介绍这些步骤。
1. 在HTML页面中添加文件上传表单
首先,在你的HTML页面中添加一个文件上传表单,如下所示:
<form action="/upload" method="post" enctype="multipart/form-data">
<label for="file">选择文件:</label>
<input type="file" id="file" name="file"><br><br>
<input type="submit" value="上传">
</form>
其中,action
属性指定表单提交的目标URL,方法是POST,enctype
属性是必要的,因为它指定要使用的编码类型,这里是multipart/form-data
类型,这种类型可以支持文件上传。
2. 编写Servlet来处理文件上传请求
然后,我们需要编写一个Servlet来处理用户的文件上传请求。首先,需要在web.xml文件中添加一个Servlet的映射。
<servlet>
<servlet-name>uploadServlet</servlet-name>
<servlet-class>com.example.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uploadServlet</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
其中,servlet-name
指定了Servlet的名称,servlet-class
则指定了Servlet的类路径。同时,servlet-mapping
则用于将URL请求映射到Servlet。
接下来,我们就需要实现com.example.UploadServlet
类,代码示例如下:
package com.example;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String UPLOAD_DIRECTORY = "uploads"; // 上传目录
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 检查请求是否为multipart/form-data
if (!ServletFileUpload.isMultipartContent(request)) {
// 如果不是则停止
PrintWriter writer = response.getWriter();
writer.println("Error: 表单必须包含 enctype=multipart/form-data");
writer.flush();
return;
}
// 配置上传参数
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存临界值
factory.setSizeThreshold(MEMORY_THRESHOLD);
// 设置临时存储目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置最大文件上传值
upload.setFileSizeMax(MAX_FILE_SIZE);
// 设置最大请求值 (包含文件和表单数据)
upload.setSizeMax(MAX_REQUEST_SIZE);
// 中文处理
upload.setHeaderEncoding("UTF-8");
// 构造临时路径来存储上传的文件
// 这个路径相对当前应用的目录
String uploadPath = getServletContext().getRealPath("/") + File.separator + UPLOAD_DIRECTORY;
// 如果目录不存在则创建
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
// 解析请求的内容提取文件数据
@SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
// 迭代表单数据
for (FileItem item : formItems) {
// 处理不在表单中的字段
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// 保存文件到硬盘
item.write(storeFile);
request.setAttribute("message", "文件上传成功!");
}
}
}
} catch (Exception ex) {
request.setAttribute("message", "发生错误: " + ex.getMessage());
}
// 跳转到 message.jsp
getServletContext().getRequestDispatcher("/message.jsp").forward(request, response);
}
}
3. 使用Apache的文件上传组件来解析文件上传请求
上述代码使用了Apache的文件上传组件,org.apache.commons.fileupload
。该组件提供了一个非常方便的API,可以处理文件上传请求。具体来说,以下是该攻略的一些关键部分:
DiskFileItemFactory
: 文件上传的临时文件存储,它的默认构造函数将全部的二进制数据存储在内存,使用过多内存,因此使用setDefaultRepository
将一部分存在硬盘上,该类还提供一个API
来修改这个允许在内存中存储的数据的量。ServletFileUpload
: 文件上传的辅助类。ServletFileUpload
包含一个FileItemFactory
,它负责管理上传文件的存储,并将这些文件项存储在内存,或临时存储在磁盘中。- 构造实际的路径,并创建一个目录以存储上传文件。
在获取参数之前,我们将检查请求是否为multipart/form-data
,这是我们是否真正处理文件上传的标志。我们也设置了一些UploadLimits来限制用户的上传大小。
然后,我们解析请求的文件和传输数据。如果是文件数据,我们将其保存到服务器的文件系统中。
4. 保存文件到指定位置并返回上传结果给用户
处理完文件上传请求后,我们需要将上传结果返回给用户,通常是返回一个确认消息。这时,我们需要将结果存储到request的属性中,然后使用JSP Page显示。
可以创建一个名为message.jsp
的页面,其中包含以下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传结果</title>
</head>
<body>
<h1>文件上传结果</h1>
<p>${message}</p>
</body>
</html>
其中,${message}
表示之前在Servlet中设置的message
属性值,即文件上传结果。
至此,Java基于Servlet实现文件上传功能的完整攻略就介绍完了。
示例1
假设我们的项目名为FileUploadDemo
,我们可以将以下示例代码保存为.jsp
文件,然后部署到我们的Tomcat Web服务器上:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传示例</title>
</head>
<body>
<h1>文件上传示例</h1>
<form action="http://localhost:8080/FileUploadDemo/upload" method="post" enctype="multipart/form-data">
<label for="file">文件:</label> <input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="上传">
</form>
</body>
</html>
注意,文件上传表单的action
属性应该设置为我们之前配置的上传Servlet路径,即/upload
。
示例2
除此之外,我们还可以使用Java内置的HttpURLConnection
类来实现文件上传,示例代码如下:
package com.example;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class FileUploader {
public static void main(String[] args) throws Exception {
String serverUrl = "http://localhost:8080/FileUploadDemo/upload";
String filePath = "/Users/user1/Documents/Book.pdf";
File uploadFile = new File(filePath);
String boundary = "-----------------------------" + System.currentTimeMillis();
HttpURLConnection connection = (HttpURLConnection) new URL(serverUrl).openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
connection.setRequestProperty("User-Agent", "Java File Uploader/1.0");
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes("--" + boundary + "\r\n");
outputStream.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + uploadFile.getName() + "\"\r\n");
outputStream.writeBytes("Content-Type: application/octet-stream\r\n\r\n");
FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.writeBytes("\r\n--" + boundary + "--\r\n");
inputStream.close();
outputStream.flush();
outputStream.close();
System.out.println(connection.getResponseCode());
System.out.println(connection.getResponseMessage());
}
}
这个示例代码读取本地文件/Users/user1/Documents/Book.pdf
并将其上传到指定的Web服务器。它使用了HttpURLConnection
类来做Http传输并指定了请求方式POST
、上传文件的Content-Type
以及POST数据的分隔符。文件内容则通过DataOutputStream
来写入RequestBody之内。值得注意的是,文件数据写入完成后,也要加上一个分隔符和标志结束。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java基于servlet实现文件上传功能解析 - Python技术站