如何使用 ajax 将文件上传到 asp.net mvc 控制器操作

Posted

技术标签:

【中文标题】如何使用 ajax 将文件上传到 asp.net mvc 控制器操作【英文标题】:How to upload files using ajax to asp.net mvc controller action 【发布时间】:2016-12-06 18:57:16 【问题描述】:

我有这个提交代码,

$('#form').on('submit',function (e) 
    e.preventDefault();
    //var file = $("#productImg");
    var fileUpload = $("#productImg").get(0);
    var files = fileUpload.files;


    var form = $("#form");
    var formData = new FormData();
    formData.append("product", form.serialize());

    // Looping over all files and add it to FormData object  
    for (var i = 0; i < files.length; i++) 
        formData.append(files[i].name, files[i]);
    
    //formData.append("file", file);

    $.ajax(
        type: 'POST',
        url: baseUrl + 'Controller/Action',
        data: formData,
        processData: false,
        contentType: false,
        success: function (data) 
        
    );
);

这是我的控制器:

  public JsonResult AddProduct(ProductModel product) // data is binded in the model if I remove content type property
    
        var isSuccess = false;

        if (product != null)
        
            try
            
                if (Request.Files.Count > 0) // works ok if I added the content type property
                
                    var sadas = "sad";
                

所以这里发生的事情是我将serialized form 数据与上传的文件一起发送到 mvc 控制器中。

这里的问题是,当我添加这个ajax属性contentType: false,时,我可以成功回发文件,但是绑定的模型是空的。

另一方面,如果我删除这个属性,绑定的模型就可以正常工作。但问题是文件没有在服务器中发送。

我怎样才能做到这一点?我希望在服务器端发送表单和图像。

更新 这现在可以工作了,我唯一改变的就是这个

formData.append("product", form.serialize());

var other_data = $('#addProductForm').serializeArray(); $.each(other_data, function (key, input) formData.append(input.name, input.value); );

有人可以解释发生了什么吗?我不知道

【问题讨论】:

假设 fil 输入也在您的表单标签中,那么您只需要var formData = new FormData($("#form").get(0)); - 请参阅this answer @StephenMuecke 谢谢!这可以简化我的代码 【参考方案1】:

不幸的是,jQuery serialize() 方法不会包含输入文件元素。因此,您的文件不会包含在序列化值中。

您可以做的是,创建一个FormData 对象,将文件附加到该对象。您还需要将表单字段值附加到同一个 FormData 对象。您可以简单地遍历所有输入字段并添加它。

当您将文件添加到表单数据时,您需要提供一个与您将在 HttpPost 操作方法中使用的参数相匹配的名称。

这应该可行。

var fileUpload = $("#productImg").get(0);
var files = fileUpload.files;

var formData = new FormData();

// Looping over all files and add it to FormData object  
for (var i = 0; i < files.length; i++) 
    console.log('(files[i].name:' + files[i].name);
    formData.append('productImg', files[i]);


// You can update the jquery selector to use a css class if you want
$("input[type='text'").each(function (x, y) 
    formData.append($(y).attr("name"), $(y).val());
);

$.ajax(
    type: 'POST',
    url:  'ReplaceHereYourUrltotheActionMethod',
    data: formData,
    processData: false,
    contentType: false,
    success: function (data) 
    
);

还有你的action方法,你可以再添加一个IEnumerable&lt;HttpPostedFileBase&gt;类型的参数,和我们给表单数据设置的名字一样,就是productImg

[HttpPost]
public virtual ActionResult Index(ProductModel model, 
                                               IEnumerable<HttpPostedFileBase> productImg)

  // to do :Look through productImg and do something  

【讨论】:

你能解释一下我更新的问题吗?顺便说一句,你的答案是正确的 你能解释一下为什么Action方法中有2个参数,而你只是在post方法中发送一个formdata吗?【参考方案2】:

对于 ASP.NET Core,您可以从您的模型开始:

public class FilesViewModel

    public Guid? ParentObjectId  get; set;  // if you wish to associate these files with some parent record
    public IEnumerable<IFormFile> Files  get; set; 

你的控制器:

[HttpPost]
public JsonResult UploadFiles(FilesViewModel model)

    if (ModelState.IsValid)
    
        // your code here
        // see https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads
    

您的视图(或视图组件):

@model YourProject.ViewModels.EventFilesViewModel
<form method="post" enctype="multipart/form-data">
    <input type="hidden" asp-for="ParentObjectId" />
    <input type="file" asp-for="Files" multiple />
    <span asp-validation-for="Files" class="text-danger"></span>
    <input type="button" id="btnEventFilesUpload" value="Upload Selected Files" class="btn btn-default" />
</form>

最后,javascript(根据 Shyju 的回答修改以传递 ParentObjectId):

$(function () 
    $("#btnEventFilesUpload").click(function (evt) 
        var fileUpload = $("#Files").get(0);
        var files = fileUpload.files;
        var data = new FormData();
        for (var i = 0; i < files.length; i++) 
            data.append('Files', files[i]);
        
        // if you wish to associate these files with some parent record
        data.append('ParentObjectId', $('#ParentObjectId').val());
        $.ajax(
            type: "POST",
            url: "/Event/UploadFiles",
            contentType: false,
            processData: false,
            data: data,
            success: function (message) 
                alert(message);
            ,
            error: function () 
                alert("There was error uploading files!");
            
        );
    );
);

【讨论】:

以上是关于如何使用 ajax 将文件上传到 asp.net mvc 控制器操作的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net 使用 Ajax 上传多个文件

如何在 asp.net 中使用 AJAX 文件上传来限制文件大小?

如何使用ajax在asp.net mvc中上传多个图像

ASP.NET 用AJAX在页面上传头像,不能异步刷新?

我可以在 asp.net(vb) 中自定义 ajax 文件上传吗?

asp.net mvc  Ajax.BeginForm 异步上传图片的问题