【问题标题】:AJAX: Asynchronously posting a file to a serverAJAX:将文件异步发布到服务器
【发布时间】:2016-06-20 11:44:11
【问题描述】:

我想在不发布表单的情况下将文件异步发布到服务器。我有以下代码:

var fileInput = document.getElementById('FileInput');
var file = fileInput.files[0];
var formData = new FormData();
formData.append('file', file, file.name);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://servername/controllername/AnalyseFile', true);
xhr.setRequestHeader('Content-Type', 'multipart/form-data');
xhr.send(formData);

但是,当该方法在服务器上执行时,帖子正文不包含任何文件。以下来自 ASP.NET MVC4:

[HttpPost]
public JsonResult AnalyseFile()
{
  int filesCount = Request.Files.Count;
  if(filesCount == 0) { throw new Exception('no files...'); }
  // do stuff
}

Files 集合不包含文件,我不知道为什么。任何帮助表示赞赏。

【问题讨论】:

  • 虽然可能在不使用表单的情况下上传文件 - 你为什么要这样做?如果要保存整页回帖,您可以只使用部分表单。这是一个示例:stackoverflow.com/questions/21675176/…
  • @wazdev 我根本不想提交表单,我想在用户仍在浏览器中工作时抢先上传文件并用它做一些事情并返回结果到浏览器。同样,我要做的就是将文件异步发布到服务器,并让服务器将有关文件的一些元数据返回给我将动态显示的浏览器。
  • @DavidPine 感谢您的回答,但据我所知,这只是将表单提交到服务器。我想将文件异步发送到服务器并让它分析文件并发送回一些元数据而不提交表单。

标签: javascript c# ajax asp.net-mvc-4 asynchronous


【解决方案1】:

在视图中,您可以:

<form>
<input name="input1" id="input1"/>
<input name="input2" id="input2"/>
<input name="input3" id="input3"/>
...
<input id="SelectedFile" name="SelectedFile" type="file"/>
</form>

还有 Javascript:

function AttLogic(_url, _data, _callback) {
    $.ajax({
        url: _url,
        type: 'POST',
        xhr: function () {
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) { }
            return myXhr;
        },
        data: _data,
        cache: !1,
        success: _callback,
        contentType: !1,
        processData: !1
    });
}

function FormDataCustom(f) {
    var __frm = jQuery(f), data = new FormData(f);
    $(':disabled[name]', __frm).each(function () {
        data.append(this.name, $(this).val());
    });
    return data;
}

function SaveLogic(){
var dt = FormDataCustom(document.forms[0]);
AttLogic(yourUrl, dt, function (r) {
        //do something here
    });
}

在控制器中:

public ActionResult Save(parameter1,parameter1,..., List<HttpPostedFileBase> SelectedFile)
{
    //do something here
}

【讨论】:

    【解决方案2】:

    您需要从请求中读取 MultiPartFormData。

    据此post

    您的方法将如下所示:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    
    namespace Some.Namespace
    {
        public class SomeController : ApiController
        {
            [HttpPost]
            public async Task<JsonResult> AnalyseFile()
            {
                 if (!Request.Content.IsMimeMultipartContent())
                 {
                     //If not throw an error
                    throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
                 }
    
                 MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider("c:\\tmp\\uploads");
    
                // Read the MIME multipart content using the stream provider we just created.
                IEnumerable<HttpContent> bodyparts = await  Request.Content.ReadAsMultipartAsync(streamProvider);
    
                // Get a dictionary of local file names from stream provider.
                // The filename parameters provided in Content-Disposition header fields are the keys.
                // The local file names where the files are stored are the values.
                //depending on your version of .net, this might have been changed to FileData instead. 
                // see: https://msdn.microsoft.com/en-us/library/system.net.http.multipartformdatastreamprovider(v=vs.118).aspx
                IDictionary<string, string> bodyPartFileNames = streamProvider.BodyPartFileNames;
    
                //rest of code here
    
        }
    }
    

    我还没有测试过上面的代码,但它应该会为你指明正确的方向。

    也可以看看How To Accept a File POST

    获取最新文章:https://code.msdn.microsoft.com/AngularJS-with-Web-API-22f62a6e

    【讨论】:

    • 这是否仍然需要一个表单来发布 - 因此是“multipart/form-data”?
    • 您将执行POST 类型的请求,并将有效负载设置为文件,并将内容类型设置为多部分/表单数据。实际上,您是在发布表单的一部分,而没有进行适当的表单发布。
    • 这是 WebAPI 能够接受文件的标准设置。如果你想做一个实际的表单发布,你只需发布到控制器而不是 api。
    • 重点是我不想在用户还在填写表单时发布表单。但是,当用户仍在浏览器中工作时,我想先发制人地将文件上传到服务器。因此,需要提交表单的解决方案并不能解决我的问题。另外,我的意思是客户端(浏览器)上的任务是异步的,服务器可以像任何请求一样同步响应它。
    • 您是否考虑过多次回发同一个表单,并改为使用添加/更新逻辑处理对象的渐进式构建?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-11
    • 2014-07-14
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多