【问题标题】:Send a file as multipart through XMLHttpRequest通过 XMLHttpRequest 将文件作为多部分发送
【发布时间】:2012-03-12 20:19:14
【问题描述】:

我可以通过XMLHttpRequest 将文件作为多部分发送到 servlet 吗?

我正在制作一个表单并将其作为多部分提交,但不知何故我没有收到成功上传它的响应。我不想刷新页面,所以它必须由 Ajax 进行。

【问题讨论】:

标签: javascript ajax servlets file-upload multipart


【解决方案1】:

这只能通过 XHR FormData API(以前称为“XHR2”或“XHR Level 2”的一部分,目前称为“XHR 高级功能”)实现。

鉴于此 HTML,

<input type="file" id="myFileField" name="myFile" />

你可以上传如下:

var formData = new FormData();
formData.append("myFile", document.getElementById("myFileField").files[0]);

var xhr = new XMLHttpRequest();
xhr.open("POST", "myServletUrl");
xhr.send(formData);

XHR 将注意正确的标头和请求正文编码,并且在此示例中,文件将在服务器端以 form-data 部分的名称myFile 的形式提供。

您需要记住,旧版浏览器不支持FormData API。在caniuse.com,您可以看到它目前已在 Chrome 7+、Firefox 3.5+、Safari 5+、Internet Explorer 10+ 和Opera 12+ 中实现。

如果您使用的是 jQuery,那么您可能会想使用它的 $.val() 函数,如下所示:

formData.append("myFile", $("#myFileField").val());

但这是不正确的,因为它不会返回整个 File 对象,而只是返回 String 的文件名,因为它不包含文件内容,所以完全没用。

如果您出于某种原因不想使用 document.getElementById(),请改用以下方法之一:

formData.append("myFile", $("#myFileField").prop("files")[0]);
formData.append("myFile", $("#myFileField")[0].files[0]);

另一种方法是使用jQuery Form plugin。您的整个表单,如果在没有任何 JavaScript 代码行的情况下编写并正常运行,那么将立即使用以下行进行 ajaxified:

$("#formId").ajaxForm(function(response) {
    // Handle Ajax response here.
});

它还通过隐藏的 iframe 技巧支持文件上传。另请参阅this jQuery Form documentation 以获得深入的解释。您可能只需要更改 servlet 代码即可拦截正常(同步)和 Ajax(异步)请求。另请参阅此答案以获取具体示例:Simple calculator with JSP/Servlet and Ajax

无论哪种方式,上传的文件都应该在@MultipartConfig servlet 的doPost() 方法中可用,如下所示:

Part myFile = request.getPart("myFile");

或者,如果您仍在使用 Servlet 2.5 或更早版本,请按常规方式使用 Apache Commons FileUpload。另请参阅此答案以获取具体示例:How can I upload files to a server using JSP/Servlet?

【讨论】:

  • 如果在我们的页面中我们自动生成许多输入文件会发生什么?我们可以生成 ID 吗?
  • @BalusC 我想知道为什么没有关于 XMLHttpRequest + FormData 如何以及为什么在 MDN 或其他地方自动设置标题的信息(谷歌搜索了很多)。每当我设置Content-type', 'multipart/form-data' 时,我的请求都会失败,但如果未指定标头则可以。但为什么呢?
【解决方案2】:

无法使用 XMLHttpRequest 发送multipart/form-data(尽管在现代浏览器中可以使用XHR2。请参阅BalusC's answer)。

实现您想要的一个常见方法是使用常规form,但改为使用iframe。这样,上传时只会刷新iframe

【讨论】:

  • 其实我想要一个响应文件是否上传。另外,我想要上传图片的位置。
  • Tejasva:看Napolux的例子,它指定了上传完成后如何在父窗口调用js函数。它也可以提供图像位置。
  • @LinusGThiel 这是可能的。请参阅 BalusC 的回答。
  • 是的,XHR2 可以。在现代浏览器中,还有 FileAPI 和其他很酷的功能。也许我应该尝试解释如何实现这一点,以及对旧浏览器的回退等。老实说,我不确定我是否会以一种好的方式向提问者传达这一点。我同意 BalusC 的回答比我的好。
猜你喜欢
  • 2014-05-19
  • 1970-01-01
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多