我目前使用Uploadify(Flash + Ajax)成功地将文件上传到Servlet(使用OWASP ESAPI覆盖的Commons Upload),但我想知道如何构建HTML5支持,或者更准确地说是带有Flash支持的HTML5。
我知道如何让HTML5拖放起作用,但我无法完全弄清Java Servlet连接和/或后端的机制。
我目前使用Uploadify(Flash + Ajax)成功地将文件上传到Servlet(使用OWASP ESAPI覆盖的Commons Upload),但我想知道如何构建HTML5支持,或者更准确地说是带有Flash支持的HTML5。
我知道如何让HTML5拖放起作用,但我无法完全弄清Java Servlet连接和/或后端的机制。
<form enctype="multipart/form-data">
没有区别。你只需要让HTML5 / JS代码发送一个带有拖放文件的multipart/form-data
请求,这与使用常规的<input type="file">
字段发送的请求完全相同。我假设你只是不知道如何使用HTML5 / JS实现这一点。File
API,XHR2 FormData
和XMLHttpRequestUpload
API来实现此目的。drop
事件处理程序应该是什么样子:function dropUpload(event) {
event.stopPropagation();
event.preventDefault();
var formData = new FormData();
formData.append("file", event.dataTransfer.files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "uploadServlet");
xhr.send(formData);
}
就是这样。此示例假定servlet映射在URL模式/uploadServlet
上。在此示例中,文件以通常的方式作为具有字段名file
的FileItem
实例在Apache Commons FileUpload中可用。
如果您想了解更高级的内容,例如附加事件处理程序以监视进度等,请查看以下博客:
我已经使用以下SSCCE进行了一些测试:
<!DOCTYPE html>
<html lang="en">
<head>
<title>HTML5 drag'n'drop file upload with Servlet</title>
<script>
window.onload = function() {
var dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", noop, false);
dropbox.addEventListener("dragexit", noop, false);
dropbox.addEventListener("dragover", noop, false);
dropbox.addEventListener("drop", dropUpload, false);
}
function noop(event) {
event.stopPropagation();
event.preventDefault();
}
function dropUpload(event) {
noop(event);
var files = event.dataTransfer.files;
for (var i = 0; i < files.length; i++) {
upload(files[i]);
}
}
function upload(file) {
document.getElementById("status").innerHTML = "Uploading " + file.name;
var formData = new FormData();
formData.append("file", file);
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.addEventListener("load", uploadComplete, false);
xhr.open("POST", "uploadServlet", true); // If async=false, then you'll miss progress bar support.
xhr.send(formData);
}
function uploadProgress(event) {
// Note: doesn't work with async=false.
var progress = Math.round(event.loaded / event.total * 100);
document.getElementById("status").innerHTML = "Progress " + progress + "%";
}
function uploadComplete(event) {
document.getElementById("status").innerHTML = event.target.responseText;
}
</script>
<style>
#dropbox {
width: 300px;
height: 200px;
border: 1px solid gray;
border-radius: 5px;
padding: 5px;
color: gray;
}
</style>
</head>
<body>
<div id="dropbox">Drag and drop a file here...</div>
<div id="status"></div>
</body>
</html>
并且这个UploadServlet
利用了新的Servlet 3.0 HttpServletRequest#getPart()
API:
@MultipartConfig
@WebServlet("/uploadServlet")
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Part file = request.getPart("file");
String filename = getFilename(file);
InputStream filecontent = file.getInputStream();
// ... Do your file saving job here.
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
response.getWriter().write("File " + filename + " successfully uploaded");
}
private static String getFilename(Part part) {
for (String cd : part.getHeader("content-disposition").split(";")) {
if (cd.trim().startsWith("filename")) {
String filename = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
return filename.substring(filename.lastIndexOf('/') + 1).substring(filename.lastIndexOf('\\') + 1); // MSIE fix.
}
}
return null;
}
}
您需要多部分配置,例如:
@MultipartConfig(fileSizeThreshold = 1024 * 1024,
maxFileSize = 1024 * 1024 * 5,
maxRequestSize = 1024 * 1024 * 5 * 5)
if
检查替换为对files
的for
循环。调用xhr.open()
时,将第三个参数(async)设置为false
。它将同步运行。您只会错过进度条支持。我已编辑了示例。至于 jQuery,据我所知,它还没有 XHR2 支持。毕竟它只是 JavaScript,我不明白为什么上面的示例应该在 jQuery 中完成。也许元素选择器,但不包括其他任何内容。可能已经有 jQuery 插件支持新的 XHR2。 - BalusC