jQuery在ASP.NET MVC中上传文件的Ajax方法

88

我在视图中有一个文件

<form id="upload" enctype="multipart/form-data">
   <input type="file" name="fileUpload" id="fileUpload" size="23" />
</form>

还有一个ajax请求

$.ajax({
    url: '<%=Url.Action("JsonSave","Survey")  %>',
    dataType: 'json',
    processData: false,
    contentType: "multipart/mixed",
    data: {
        Id: selectedRow.Id,
        Value: 'some date was added by the user here :))'
    },
    cache: false,
    success: function (data) {}
});

但是在Request.Files中没有文件。ajax请求有什么问题?


JSON无法像这样上传文件。最好使用浏览器的默认上传行为。 - Hogan
5个回答

145

使用AJAX在ASP.Net MVC中上传文件

自HTML5以来,事情已经发生了变化。

JavaScript

document.getElementById('uploader').onsubmit = function () {
    var formdata = new FormData(); //FormData object
    var fileInput = document.getElementById('fileInput');
    //Iterating through each files selected in fileInput
    for (i = 0; i < fileInput.files.length; i++) {
        //Appending each file to FormData object
        formdata.append(fileInput.files[i].name, fileInput.files[i]);
    }
    //Creating an XMLHttpRequest and sending
    var xhr = new XMLHttpRequest();
    xhr.open('POST', '/Home/Upload');
    xhr.send(formdata);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            alert(xhr.responseText);
        }
    }
    return false;
}   

控制器

public JsonResult Upload()
{
    for (int i = 0; i < Request.Files.Count; i++)
    {
        HttpPostedFileBase file = Request.Files[i]; //Uploaded file
        //Use the following properties to get file's name, size and MIMEType
        int fileSize = file.ContentLength;
        string fileName = file.FileName;
        string mimeType = file.ContentType;
        System.IO.Stream fileContent = file.InputStream;
        //To save file, use SaveAs method
        file.SaveAs(Server.MapPath("~/")+ fileName ); //File will be saved in application root
    }
    return Json("Uploaded " + Request.Files.Count + " files");
}

编辑:HTML

<form id="uploader">
    <input id="fileInput" type="file" multiple>
    <input type="submit" value="Upload file" />
</form>

1
你能在这个答案中添加视图的代码和HTML吗? - Eric Bishard
很棒的博客Ajeesh!谢谢! - Eric Bishard
1
你好,有没有一种方法可以将上传的文件绑定到模型中? - Yorro
我也在使用一个区域,只需输入“Controller/Action”即可。 - mortey
@NareshRavlani 对于MVC Core,请查看此答案:https://dev59.com/yVoV5IYBdhLWcg3wIbxT#44174182 - Theotonio
显示剩余6条评论

55
现在可以通过将FormData对象传递到$.ajax请求的data属性来实现AJAX文件上传。由于OP特别要求使用jQuery实现,因此在这里提供一个示例代码:
<form id="upload" enctype="multipart/form-data" action="@Url.Action("JsonSave", "Survey")" method="POST">
    <input type="file" name="fileUpload" id="fileUpload" size="23" /><br />
    <button>Upload!</button>
</form>
$('#upload').submit(function(e) {
    e.preventDefault(); // stop the standard form submission

    $.ajax({
        url: this.action,
        type: this.method,
        data: new FormData(this),
        cache: false,
        contentType: false,
        processData: false,
        success: function (data) {
            console.log(data.UploadedFileCount + ' file(s) uploaded successfully');
        },
        error: function(xhr, error, status) {
            console.log(error, status);
        }
    });
});
public JsonResult Survey()
{
    for (int i = 0; i < Request.Files.Count; i++)
    {
        var file = Request.Files[i];
        // save file as required here...
    }
    return Json(new { UploadedFileCount = Request.Files.Count });
}

MDN上了解更多关于FormData的信息


7
美丽。谢谢!这是我在几个问题上找到的最佳答案。 - Jess
1
我特意来这里寻找jQuery解决方案,但看到标记为已回答的响应仅使用了原生JavaScript,有点失望。您的解决方案非常好,对我非常有效。非常感谢 :) - Joshua K
1
@Savage:在2020年/Chrome/ASP.NET Core MVC中进行了测试:当您没有选择任何内容时,文件为空。无论如何,答案是使用Razor和MVC控制器实现非常干净的文件上传集成。 - christophe.chapron
不调用$('#upload').submit(function。直接进入控制器并更改页面。 - Balasubramanian Ramamoorthi
@BalasubramanianRamamoorthi 如果是这样的话,你的 HTML 或 JS 可能有问题。我建议你针对你自己的情况提出一个新问题,因为上面的示例是有效和正确的。 - Rory McCrossan
显示剩余2条评论

4

你无法通过ajax上传文件,需要使用iFrame或其他技巧进行完整的postback。这主要是出于安全考虑。

这里有一个不错的文章,包括一个示例项目,由Steve Sanderson使用SWFUpload和ASP.Net MVC编写。这是我第一次在Asp.Net MVC中正确使用它时读到的东西(当时我也是MVC新手),希望对你有所帮助。


15
不是这样的;你可以通过ajax发送表单数据。 - Josh M.
9
有了HTML5中的新FormData和File对象,您确实可以通过AJAX上传文件。尝试使用此链接:https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications。 - jrista

1

我有一个Vue.js版本为v2.5.2的示例。

<form action="url" method="post" enctype="multipart/form-data">
    <div class="col-md-6">
        <input type="file" class="image_0" name="FilesFront" ref="FilesFront" />
    </div>
    <div class="col-md-6">
        <input type="file" class="image_1" name="FilesBack" ref="FilesBack" />
    </div>
</form>
<script>
Vue.component('v-bl-document', {
    template: '#document-item-template',
    props: ['doc'],
    data: function () {
        return {
            document: this.doc
        };
    },
    methods: {
        submit: function () {
            event.preventDefault();

            var data = new FormData();
            var _doc = this.document;
            Object.keys(_doc).forEach(function (key) {
                data.append(key, _doc[key]);
            });
            var _refs = this.$refs;
            Object.keys(_refs).forEach(function (key) {
                data.append(key, _refs[key].files[0]);
            });

            debugger;
            $.ajax({
                type: "POST",
                data: data,
                url: url,
                cache: false,
                contentType: false,
                processData: false,
                success: function (result) {
                    //do something
                },

            });
        }
    }
});
</script>

我花了将近两天的时间来理解这个问题,终于找到了一个解决方案。不过,能否对表单进行模型绑定呢? - Marqueone

0
如果您使用ajax提交表单,则无法使用$.ajax方法发送图像, 您必须使用经典的xmlHttpobject方法保存图像, 另一种替代方法是使用submit类型而不是button。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接