Of course! Let's dive deep into Java WebUploader.

First, a crucial clarification: "Java WebUploader" isn't a single, monolithic library. It's a combination of two key technologies:
- The Frontend: The WebUploader library itself. This is a popular, powerful, and feature-rich client-side JavaScript library created by Baidu (FEX Team) for handling file uploads. It's UI-agnostic and works with any HTML/CSS/JS framework.
- The Backend: A Java server-side application (e.g., using Spring Boot, Servlet API, etc.) that receives the files sent by the WebUploader client.
The "Java" part refers to the server-side implementation that handles the file processing, storage, and validation.
This guide will cover both parts, showing you how to build a complete file upload solution.
The Frontend: WebUploader Library
WebUploader is excellent because it provides a polished UI and handles many complex scenarios automatically, such as:

- Chunked Uploads: Breaking large files into smaller pieces for more reliable uploads.
- Resume Uploads: If an upload fails, it can resume from where it left off.
- File Validation: Client-side checks for file type, size, etc.
- Drag-and-Drop: A modern, intuitive user experience.
- Progress Bar: Real-time feedback on upload status.
Key Features to Understand:
- File Pickers: You can have multiple file pickers on a page.
- File Queues: Files are queued before being uploaded.
- Server API: It sends files using standard
multipart/form-datarequests, making it compatible with any server-side technology, including Java. - Events: It fires events for various actions (fileQueued, uploadStart, uploadProgress, uploadSuccess, uploadError, etc.), which you can listen to to update your UI.
The Backend: Java Implementation (using Servlet API)
We'll start with a standard Java Servlet approach, as it's the foundation. Then, we'll look at the more modern and recommended Spring Boot way.
Project Setup (Maven pom.xml)
You'll need the Apache Commons FileUpload library to handle multipart requests in a standard Java web application.
<dependencies>
<!-- For handling multipart/form-data requests -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
Servlet Implementation (FileUploadServlet.java)
This servlet will receive the file chunks, combine them if it's a chunked upload, and save the final file to a server directory.
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.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.UUID;
@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final String UPLOAD_DIR = "C:/temp/uploads/"; // A directory on your server
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Check that we have a file upload request
if (!ServletFileUpload.isMultipartContent(request)) {
// Not a multipart/form-data request
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Request type is not multipart/form-data");
return;
}
// Configure a repository (to ensure a secure temp location is used)
DiskFileItemFactory factory = new DiskFileItemFactory();
// Set temporary directory for file parts
File repository = (File) getServletContext().getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
try {
// Parse the request
List<FileItem> items = upload.parseRequest(request);
String fileName = null;
String chunk = null;
String chunks = null;
String fileMd5 = null; // WebUploader sends MD5 for chunk verification
for (FileItem item : items) {
if (item.isFormField()) {
// Handle form fields (sent by WebUploader)
String fieldName = item.getFieldName();
String value = item.getString();
switch (fieldName) {
case "name":
fileName = value;
break;
case "chunk":
chunk = value;
break;
case "chunks":
chunks = value;
break;
case "md5":
fileMd5 = value;
break;
}
} else {
// This is the actual file part
if (fileName == null) {
fileName = item.getName();
}
// If it's a chunked upload, save the chunk to a temporary file
if (chunk != null && chunks != null) {
String uniqueId = UUID.randomUUID().toString();
File chunkFile = new File(UPLOAD_DIR, uniqueId + ".part");
try (InputStream uploadedStream = item.getInputStream();
OutputStream out = new java.io.FileOutputStream(chunkFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = uploadedStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
// Respond to the client that the chunk was received
response.getWriter().write("{\"success\": true}");
return;
} else {
// It's a simple, non-chunked upload. Save the file directly.
File fileToSave = new File(UPLOAD_DIR, fileName);
try (InputStream uploadedStream = item.getInputStream();
OutputStream out = new java.io.FileOutputStream(fileToSave)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = uploadedStream.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
// Respond to the client that the file was uploaded
response.getWriter().write("{\"success\": true, \"file\": \"" + fileToSave.getName() + "\"}");
return;
}
}
}
// If we get here, it means we received all chunks and need to combine them
if (chunks != null && Integer.parseInt(chunks) > 1) {
combineChunks(fileName, chunks);
response.getWriter().write("{\"success\": true, \"file\": \"" + fileName + "\"}");
}
} catch (Exception e) {
e.printStackTrace();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "File upload failed: " + e.getMessage());
}
}
private void combineChunks(String originalFileName, int totalChunks) throws IOException {
File finalFile = new File(UPLOAD_DIR, originalFileName);
try (OutputStream out = new java.io.FileOutputStream(finalFile)) {
for (int i = 0; i < totalChunks; i++) {
File chunkFile = new File(UPLOAD_DIR, i + ".part"); // WebUploader names chunks numerically
if (chunkFile.exists()) {
try (InputStream in = new java.io.FileInputStream(chunkFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
chunkFile.delete(); // Delete the chunk after combining
}
}
}
}
}
Note on Chunking: The WebUploader client sends chunks with sequential names (e.g., part, part, etc.). The server-side logic needs to be aware of this naming convention to reassemble the file correctly. The above code provides a simplified version. A production system should use a unique identifier for each file's chunks to avoid conflicts.

Putting It All Together: Frontend HTML & JavaScript
Now, let's create the HTML page that uses WebUploader to send files to our Java servlet.
Step 1: Include WebUploader CSS and JS
Download the WebUploader files from its GitHub repository or use a CDN.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">Java WebUploader Demo</title>
<!-- 引入 WebUploader 的 CSS -->
<link rel="stylesheet" type="text/css" href="webuploader-0.1.8/dist/webuploader.css">
<style>
.wu-example {
position: relative;
margin: 50px 0;
padding: 20px;
border: 1px dashed #ccc;
border-radius: 6px;
}
#picker {
display: inline-block;
line-height: 1.428571429;
font-size: 14px;
color: #555;
vertical-align: middle;
cursor: pointer;
background-color: #eee;
border: 1px solid #ddd;
border-radius: 4px;
padding: 6px 12px;
}
#fileList {
max-height: 200px;
}
.file-item {
padding: 5px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
}
</style>
</head>
<body>
<div id="uploader" class="wu-example">
<div id="picker">选择文件</div>
<div id="fileQueue"></div>
<div id="fileList" class="uploader-list"></div>
</div>
<!-- 引入 jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- 引入 WebUploader 的 JS -->
<script type="text/javascript" src="webuploader-0.1.8/dist/webuploader.js"></script>
<script>
$(function() {
var uploader = WebUploader.create({
// swf文件路径
swf: 'webuploader-0.1.8/dist/Uploader.swf',
// 文件接收服务端。
server: 'http://localhost:8080/your-app-name/upload', // !!! IMPORTANT: Change this to your servlet URL
// 选择文件的按钮,可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#picker',
// 不压缩image, 默认如果是jpeg,会压缩!!
resize: false,
// 开启分片上传
chunked: true,
// 分片大小
chunkSize: 2 * 1024 * 1024, // 2M
// 最大上传并发数
threads: 3,
// 自动上传
auto: true
});
// 当有文件被添加进队列的时候
uploader.on('fileQueued', function(file) {
var $li = $(
'<div id="' + file.id + '" class="file-item">' +
'<span class="title">' + file.name + '</span>' +
'<span class="progress"></span>' +
'<span class="state">等待上传...</span>' +
'</div>'
);
$('#fileList').append($li);
});
// 文件上传过程中创建进度条实时显示
uploader.on('uploadProgress', function(file, percentage) {
var $li = $('#'+file.id),
$percent = $li.find('.progress');
$percent.text('上传中 ' + Math.round(percentage * 100) + '%');
});
// 文件上传成功
uploader.on('uploadSuccess', function(file, response) {
$('#'+file.id).find('.state').text('已上传');
console.log('Upload success:', response);
});
// 文件上传失败
uploader.on('uploadError', function(file) {
$('#'+file.id).find('.state').text('上传出错');
});
// 完成上传,无论成功失败
uploader.on('uploadComplete', function(file) {
$('#'+file.id).find('.state').text('完成');
});
});
</script>
</body>
</html>
The Modern & Recommended Way: Spring Boot
Using the Servlet API is great for understanding the fundamentals, but in a real-world application, you'd almost certainly use a framework like Spring Boot. It simplifies file handling immensely.
Spring Boot Controller (FileUploadController.java)
Spring Boot automatically configures a MultipartFile handler that takes care of all the low-level details.
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@RestController
public class FileUploadController {
// Define a directory to store uploaded files
private static final String UPLOADED_FOLDER = "/path/to/your/upload/directory/"; // Use an absolute path
@PostMapping("/api/upload")
public String handleFileUpload(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "Please select a file to upload";
}
try {
// Create the upload directory if it doesn't exist
Path uploadPath = Paths.get(UPLOADED_FOLDER);
if (!Files.exists(uploadPath)) {
Files.createDirectories(uploadPath);
}
// Get the original filename
String originalFilename = file.getOriginalFilename();
// Generate a unique filename to avoid conflicts
String uniqueFilename = UUID.randomUUID().toString() + "_" + originalFilename;
// Save the file to the target location
Path destinationFile = uploadPath.resolve(uniqueFilename);
Files.copy(file.getInputStream(), destinationFile);
return "You successfully uploaded '" + uniqueFilename + "' to '" + UPLOADED_FOLDER + "'";
} catch (IOException e) {
e.printStackTrace();
return "Failed to upload file: " + e.getMessage();
}
}
}
Why Spring Boot is better for this:
- Simplicity: No need for
commons-fileupload. TheMultipartFileobject is clean and easy to use. - Automatic Configuration: Spring Boot handles all the servlet container setup.
- Chunked/Resume Support: For chunked uploads, you would need to build a more sophisticated controller that can save chunks and reassemble them, similar to the servlet example, but the
MultipartFileAPI is still the entry point. Libraries like Spring Content can even make this declarative.
Summary
| Aspect | Servlet API | Spring Boot |
|---|---|---|
| Setup | Manual web.xml, add dependencies |
@SpringBootApplication, auto-configuration |
| File Handling | Parse List<FileItem> |
Use MultipartFile parameter |
| Code | More boilerplate, manual I/O | Concise, high-level API |
| Chunking | Manual implementation required | Manual implementation required, but MultipartFile makes it cleaner |
| Recommendation | Good for learning, simple apps | Highly recommended for all new projects |
In conclusion, "Java WebUploader" is a powerful combination. The WebUploader frontend provides an excellent user experience, and a Java backend (especially with Spring Boot) provides a robust and scalable server to handle the file storage.
