如何使用带有进度条的ASP.NET MVC4 Web Api上传大文件

yga*_*don 16 c# asp.net asp.net-mvc asp.net-mvc-4

如何使用ASP.NET MVC4 Web Api上传大文件
并获得进展?

我看到这篇文章,我知道如何处理上传的文件,但我如何获得进度数据? 如何接受文件POST

请不要发送链接上传产品.我想了解如何在MVC4 Web Api中处理这个...这里是一个处理MVC4 WebApi文件上传的示例代码

    public async Task<HttpResponseMessage> Post()
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            var path = HttpContext.Current.Server.MapPath("~/App_Data");

            var provider = new MultipartFormDataStreamProvider(path);

            await Request.Content.ReadAsMultipartAsync(provider).ContinueWith(t =>
            {
                if (t.IsFaulted || t.IsCanceled)
                    throw new HttpResponseException(HttpStatusCode.InternalServerError);
            });

            return Request.CreateResponse(HttpStatusCode.OK); 
        }
        else
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在,当

   await Request.Content.ReadAsMultipartAsync(provider)
Run Code Online (Sandbox Code Playgroud)

我怎样才能得到字节加载的方式?

Mri*_*dul 20

默认情况下,在两个位置上传文件的大小有限制.一个在请求级别,第二个,如果您在IIS上托管,那么在Web服务器级别.我添加了几个配置,如本博客中所述,我能够上传一个36mb文件,没有任何问题.我已在下面发布了该片段.

基本上

1.

  <system.web> 
    <httpRuntime maxRequestLength="2097152"/>
  </system.web>
Run Code Online (Sandbox Code Playgroud)

2.

<system.webServer> 
  <security> 
      <requestFiltering> 
         <requestLimits maxAllowedContentLength="2147483648" /> 
      </requestFiltering> 
  </security><system.webServer> 
Run Code Online (Sandbox Code Playgroud)

如果您愿意,很容易找到加载到服务器中的文件的大小.在你的代码中

在读取流中的filedata时,对于文件数据中的每个项目,您可以读取本地文件名,如下所示.

 string savedFile = fileData.LocalFileName;
 // use the file info class to derive properties of the uploaded file
 FileInfo file = new FileInfo(savedFile);
//this will give the size of the uploaded file 
long size = file.length/1024
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.我想知道为什么这会被标记下来?

  • 感谢有用的信息,我已经知道上传限制,而不是我要求的,我找不到一种方法来获取上传的字节的进度,我的行动是在所有请求正文上传后调用. (6认同)

小智 6

我使用这个解决方案:

public class UploadController : ApiController
{
    private static ConcurrentDictionary<string, State> _state = new ConcurrentDictionary<string, State>();

    public State Get(string id)
    {
        State state;

        if (_state.TryGetValue(id, out state))
        {
            return state;
        }

        return null;
    }


    public async Task<HttpResponseMessage> Post([FromUri] string id)
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            var state = new State(Request.Content.Headers.ContentLength);
            if (!_state.TryAdd(id, state))
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.Conflict));

            var path = System.Web.Hosting.HostingEnvironment.MapPath("~/App_Data");

            var provider = new FileMultipartStreamProvider(path, state.Start, state.AddBytes);

            await Request.Content.ReadAsMultipartAsync(provider).ContinueWith(t =>
            {
                _state.TryRemove(id, out state);

                if (t.IsFaulted || t.IsCanceled)
                    throw new HttpResponseException(HttpStatusCode.InternalServerError);
            });


            return Request.CreateResponse(HttpStatusCode.OK);
        }
        else
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
        }
    }
}


public class State
{
    public long? Total { get; set; }

    public long Received { get; set; }

    public string Name { get; set; }

    public State(long? total = null)
    {
        Total = total;
    }

    public void Start(string name)
    {
        Received = 0;
        Name = name;
    }

    public void AddBytes(long size)
    {
        Received = size;
    }
}

public class FileMultipartStreamProvider : MultipartStreamProvider
{
    private string _rootPath;
    private Action<string> _startUpload;
    private Action<long> _uploadProgress;

    public FileMultipartStreamProvider(string root_path, Action<string> start_upload, Action<long> upload_progress)
        : base()
    {
        _rootPath = root_path;
        _startUpload = start_upload;
        _uploadProgress = upload_progress;
    }

    public override System.IO.Stream GetStream(HttpContent parent, System.Net.Http.Headers.HttpContentHeaders headers)
    {
        var name = (headers.ContentDisposition.Name ?? "undefined").Replace("\"", "").Replace("\\", "_").Replace("/", "_").Replace("..", "_");

        _startUpload(name);

        return new WriteFileStreamProxy(Path.Combine(_rootPath, name), _uploadProgress);
    }

}

public class WriteFileStreamProxy : FileStream
{
    private Action<long> _writeBytes;

    public WriteFileStreamProxy(string file_path, Action<long> write_bytes)
        : base(file_path, FileMode.Create, FileAccess.Write)
    {
        _writeBytes = write_bytes;
    }

    public override void EndWrite(IAsyncResult asyncResult)
    {
        base.EndWrite(asyncResult);

#if DEBUG
        System.Threading.Thread.Sleep(100);
#endif

        if (_writeBytes != null)
            _writeBytes(base.Position);

    }

    public override void Write(byte[] array, int offset, int count)
    {
        base.Write(array, offset, count);

#if DEBUG
        System.Threading.Thread.Sleep(100);
#endif
        if (_writeBytes != null)
            _writeBytes(base.Position);
    }
}
Run Code Online (Sandbox Code Playgroud)

和非缓冲输入流的小配置:

config.Services.Replace(typeof(IHostBufferPolicySelector), new CustomPolicy());
Run Code Online (Sandbox Code Playgroud)

实现了这个:

public class CustomPolicy : System.Web.Http.WebHost.WebHostBufferPolicySelector
{
    public override bool UseBufferedInputStream(object hostContext)
    {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)