我正在为我的表单使用 jQuery 和 Ajax 来提交数据和文件,但我不确定如何在一个表单中同时发送数据和文件?
我目前对这两种方法几乎相同,但将数据收集到数组中的方式不同,数据使用 .serialize();
但文件使用 = new FormData($(this)[0]);
是否可以结合这两种方法通过 Ajax 以一种形式上传文件和数据?
数据 jQuery、Ajax 和 html
$("form#data").submit(function(){
var formData = $(this).serialize();
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="data" method="post">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<button>Submit</button>
</form>
文件 jQuery、Ajax 和 html
$("form#files").submit(function(){
var formData = new FormData($(this)[0]);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
async: false,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
return false;
});
<form id="files" method="post" enctype="multipart/form-data">
<input name="image" type="file" />
<button>Submit</button>
</form>
如何结合以上内容,以便通过 Ajax 以一种形式发送数据和文件?
我的目标是能够通过 Ajax 在一个帖子中发送所有这些表格,这可能吗?
<form id="datafiles" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
FormData
方法应该适用于包含您想要的任何内容的表单,而不仅仅是文件上传字段;虽然它没有得到广泛支持。
FormData
时应提交所有表单数据
我遇到的问题是使用了错误的 jQuery 标识符。
您可以使用 ajax 以一种形式上传数据和文件。
PHP + HTML
<?php
print_r($_POST);
print_r($_FILES);
?>
<form id="data" method="post" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button>Submit</button>
</form>
jQuery + Ajax
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.ajax({
url: window.location.pathname,
type: 'POST',
data: formData,
success: function (data) {
alert(data)
},
cache: false,
contentType: false,
processData: false
});
});
精简版
$("form#data").submit(function(e) {
e.preventDefault();
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function(data) {
alert(data);
});
});
另一种选择是使用 iframe 并将表单的目标设置为它。
你可以试试这个(它使用 jQuery):
function ajax_form($form, on_complete)
{
var iframe;
if (!$form.attr('target'))
{
//create a unique iframe for the form
iframe = $("<iframe></iframe>").attr('name', 'ajax_form_' + Math.floor(Math.random() * 999999)).hide().appendTo($('body'));
$form.attr('target', iframe.attr('name'));
}
if (on_complete)
{
iframe = iframe || $('iframe[name="' + $form.attr('target') + '"]');
iframe.load(function ()
{
//get the server response
var response = iframe.contents().find('body').text();
on_complete(response);
});
}
}
它适用于所有浏览器,您无需序列化或准备数据。不利的一面是您无法监控进度。
此外,至少对于 chrome,该请求不会出现在开发人员工具的“xhr”选项卡中,而是出现在“doc”下
我在带有 HttpPostedFilebase 的 ASP.Net MVC 中遇到了同样的问题,而不是在提交时使用表单,我需要在单击时使用按钮,我需要在需要做一些事情的地方点击按钮,然后如果一切正常,提交表单,这就是我如何让它工作
$(".submitbtn").on("click", function(e) {
var form = $("#Form");
// you can't pass Jquery form it has to be javascript form object
var formData = new FormData(form[0]);
//if you only need to upload files then
//Grab the File upload control and append each file manually to FormData
//var files = form.find("#fileupload")[0].files;
//$.each(files, function() {
// var file = $(this);
// formData.append(file[0].name, file[0]);
//});
if ($(form).valid()) {
$.ajax({
type: "POST",
url: $(form).prop("action"),
//dataType: 'json', //not sure but works for me without this
data: formData,
contentType: false, //this is requireded please see answers above
processData: false, //this is requireded please see answers above
//cache: false, //not sure but works for me without this
error : ErrorHandler,
success : successHandler
});
}
});
这将比正确地填充您的 MVC 模型,请确保在您的模型中,HttpPostedFileBase[] 的属性与 html 中的输入控件的名称具有相同的名称,即
<input id="fileupload" type="file" name="UploadedFiles" multiple>
public class MyViewModel
{
public HttpPostedFileBase[] UploadedFiles { get; set; }
}
contentType : "application/octet-stream"
或更短:
$("form#data").submit(function() {
var formData = new FormData(this);
$.post($(this).attr("action"), formData, function() {
// success
});
return false;
});
编辑:使用新版本的 JQuery (3.6),您还可以尝试使用 contentType 函数参数而不是 enctype
。试试 contentType: multipart/form-data
。
对我来说,如果没有 Ajax 请求中的 enctype: 'multipart/form-data'
字段,它就无法工作。我希望它可以帮助陷入类似问题的人。
尽管 enctype
已在表单属性中设置,但由于某种原因,Ajax 请求在没有明确声明的情况下不会自动识别 enctype
(jQuery 3.3.1)。
// Tested, this works for me (jQuery 3.3.1)
fileUploadForm.submit(function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: $(this).attr('action'),
enctype: 'multipart/form-data',
data: new FormData(this),
processData: false,
contentType: false,
success: function (data) {
console.log('Thank God it worked!');
}
}
);
});
// enctype field was set in the form but Ajax request didn't set it by default.
<form action="process/file-upload" enctype="multipart/form-data" method="post" >
<input type="file" name="input-file" accept="text/plain" required>
...
</form>
正如上面提到的其他人,还请特别注意 contentType
和 processData
字段。
enctype
。
enctype
字段未包含在文档中是有原因的。我还没有检查 jQuery 源代码,所以我不能肯定地说。
enctype
字段再次测试了我的代码,它不再上传文件(编码类型错误返回)。我不确定它是如何工作的,因为我没有检查 jQuery 源代码。我发布此答案的目的是帮助陷入类似问题的其他人。我不是在这里钓鱼...如果您还有其他问题/评论,让我们聊天而不是评论。
一种简单但更有效的方法:
new FormData()
本身就像一个容器(或袋子)。您可以将所有 attr 或 file 放入其中。您唯一需要附加 attribute, file, fileName
例如:
let formData = new FormData()
formData.append('input', input.files[0], input.files[0].name)
并在 AJAX 请求中传递它。例如:
let formData = new FormData()
var d = $('#fileid')[0].files[0]
formData.append('fileid', d);
formData.append('inputname', value);
$.ajax({
url: '/yourroute',
method: 'POST',
contentType: false,
processData: false,
data: formData,
success: function(res){
console.log('successfully')
},
error: function(){
console.log('error')
}
})
您可以使用 FormData 附加 n 个文件或数据。
如果您从 Script.js 文件向 Node.js 中的 Route 文件发出 AJAX 请求,请注意使用
req.body
访问数据(即文本)
req.files
访问文件(即图像、视频ETC)
提醒一下,2022 年你不需要使用 jquery。试试 js 标准Fetch API
var formData = new FormData(this);
fetch(url, {
method: 'POST',
body: formData
})
.then(response => {
if(response.ok) {
//success
alert(response);
} else {
throw Error('Server error');
}
})
.catch(error => {
console.log('fail', error);
});
下面的代码对我有用
$(function () {
debugger;
document.getElementById("FormId").addEventListener("submit", function (e) {
debugger;
if (ValidDateFrom()) { // Check Validation
var form = e.target;
if (form.getAttribute("enctype") === "multipart/form-data") {
debugger;
if (form.dataset.ajax) {
e.preventDefault();
e.stopImmediatePropagation();
var xhr = new XMLHttpRequest();
xhr.open(form.method, form.action);
xhr.onreadystatechange = function (result) {
debugger;
if (xhr.readyState == 4 && xhr.status == 200) {
debugger;
var responseData = JSON.parse(xhr.responseText);
SuccessMethod(responseData); // Redirect to your Success method
}
};
xhr.send(new FormData(form));
}
}
}
}, true);
});
在您的 Action Post 方法中,将参数作为 HttpPostedFileBase UploadFile 传递,并确保您的文件输入与您在 Action 方法的参数中提到的相同。它也应该与 AJAX Begin 形式一起使用。
请记住,您的 AJAX BEGIN 表单在这里不起作用,因为您在上面提到的代码中定义了您的 post call,并且您可以根据要求在代码中引用您的方法
我知道我回答迟了,但这对我有用
这是我实施的解决方案
var formData = new FormData();
var files = $('input[type=file]');
for (var i = 0; i < files.length; i++) {
if (files[i].value == "" || files[i].value == null) {
return false;
}
else {
formData.append(files[i].name, files[i].files[0]);
}
}
var formSerializeArray = $("#Form").serializeArray();
for (var i = 0; i < formSerializeArray.length; i++) {
formData.append(formSerializeArray[i].name, formSerializeArray[i].value)
}
$.ajax({
type: 'POST',
data: formData,
contentType: false,
processData: false,
cache: false,
url: '/Controller/Action',
success: function (response) {
if (response.Success == true) {
return true;
}
else {
return false;
}
},
error: function () {
return false;
},
failure: function () {
return false;
}
});
在我的情况下,我必须发出一个 POST 请求,其中包含通过标头发送的信息,以及使用 FormData 对象发送的文件。
我在这里使用了一些答案的组合使其工作,所以基本上最终工作的是在我的 Ajax 请求中有这五行:
contentType: "application/octet-stream",
enctype: 'multipart/form-data',
contentType: false,
processData: false,
data: formData,
其中 formData 是这样创建的变量:
var file = document.getElementById('uploadedFile').files[0];
var form = $('form')[0];
var formData = new FormData(form);
formData.append("File", file);
contentType: "application/octet-stream",
是有害的,它不会导致问题的唯一原因是因为您在两行之后将其覆盖。
enctype: 'multipart/form-data',
毫无意义。 jQuery.ajax 无法识别该参数。
您可以将它们附加到您的表单数据中,在其中添加您的文件和数据。您可以阅读此..
https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
为了更好地理解。您可以分别为您的文件检索它们 $_FILES 和为您的数据检索 $_POST 。
<form id="form" method="post" action="otherpage.php" enctype="multipart/form-data">
<input type="text" name="first" value="Bob" />
<input type="text" name="middle" value="James" />
<input type="text" name="last" value="Smith" />
<input name="image" type="file" />
<button type='button' id='submit_btn'>Submit</button>
</form>
<script>
$(document).on("click", "#submit_btn", function (e) {
//Prevent Instant Click
e.preventDefault();
// Create an FormData object
var formData = $("#form").submit(function (e) {
return;
});
//formData[0] contain form data only
// You can directly make object via using form id but it require all ajax operation inside $("form").submit(<!-- Ajax Here -->)
var formData = new FormData(formData[0]);
$.ajax({
url: $('#form').attr('action'),
type: 'POST',
data: formData,
success: function (response) {
console.log(response);
},
contentType: false,
processData: false,
cache: false
});
return false;
});
</script>
///// 其他页面.php
<?php
print_r($_FILES);
?>
$(this)[0]
只是this
的别名,所以new FormData(this)
应该足够了。async: false
似乎不需要此功能并导致移动(单线程)浏览器阻塞