如何使用 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 上传到另一个 Web 应用程序

使用 Asp.NET Core 3.1 框架将文件上传到服务器时如何使用 IFormFile 作为属性?

如何使用 .Net 4.0 中包含的 HttpClient 类将文件上传到在 IIS Express 中运行的 Asp.Net MVC 4.0 操作

如何使用 Retrofit 在 android 中调用图像上传 Web 服务 (ASP.NET) .asmx 文件

如何将带有附加数据的 FormData 文件发送到 asp.net web api ajax 调用

asp.net如何将文件下载到自己选择的位置上