通过 XMLHttpRequest 将文件作为多部分发送

IT技术 javascript ajax servlets file-upload multipart
2021-02-04 15:31:33

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

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

2个回答

这只能通过 XHR FormDataAPI 实现(以前称为“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-dataname 的一部分在服务器端可用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 表单插件您的整个表单,在没有任何 JavaScript 代码行的情况下编写和正常运行时,将立即通过以下行进行ajax化:

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

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

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

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

或者,如果您仍在使用 Servlet 2.5 或更早版本,请按常规方式使用 Apache Commons FileUpload。有关具体示例,另请参阅此答案:如何使用 JSP/Servlet 将文件上传到服务器?

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

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

实现您想要的一种常见方法是使用常规的form,而是使用iframe这样,只有iframe在上传时刷新。

实际上,无论文件是否上传,我都想要一个回应。另外,我想要上传图像的位置。
2021-03-19 15:31:33
Tejasva:看Napolux的例子,它指定了上传完成后如何在父窗口调用js函数。它还可以提供图像位置。
2021-03-22 15:31:33
@LinusGThiel 这是可能的。请参阅 BalusC 的回答。
2021-03-26 15:31:33
是的,XHR2 是可能的。对于现代浏览器,还有 FileAPI 和其他很酷的功能。也许我应该尝试解释如何实现这一点,为旧浏览器提供后备等。老实说,我不确定我是否会以良好的方式向提问者传达这一点。我同意 BalusC 的回答比我的好。
2021-04-05 15:31:33