17

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"));
        }
    }

今、いつ

   await Request.Content.ReadAsMultipartAsync(provider)

ロードされたバイト数を取得するにはどうすればよいですか?

4

3 に答える 3

20

アップロードするファイルのサイズには、デフォルトで 2 か所に制限があります。1 つはリクエスト レベルで、2 つ目は IIS でホストしている場合は Web サーバー レベルです。このブログに記載されているように、いくつかの構成を追加したところ、問題なく 36 MB のファイルをアップロードできました。以下にスニペットを掲載しました。

基本的

1.

  <system.web> 
    <httpRuntime maxRequestLength="2097152"/>
  </system.web>

2.

<system.webServer> 
  <security> 
      <requestFiltering> 
         <requestLimits maxAllowedContentLength="2147483648" /> 
      </requestFiltering> 
  </security><system.webServer> 

必要に応じて、サーバーにロードされたファイルのサイズを簡単に見つけることができます。あなたのコードで

ストリーム内のファイルデータを読み取っているときに、ファイルデータ内の各アイテムについて、以下に示すようにローカルファイル名を読み取ることができます。

 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

お役に立てれば。なぜこれがマークダウンされたのだろうか?

于 2013-03-23T05:58:56.667 に答える
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);
    }
}

バッファリングされていない入力ストリームの小さな構成:

config.Services.Replace(typeof(IHostBufferPolicySelector), new CustomPolicy());

これを実装しました:

public class CustomPolicy : System.Web.Http.WebHost.WebHostBufferPolicySelector
{
    public override bool UseBufferedInputStream(object hostContext)
    {
        return false;
    }
}
于 2014-02-28T06:49:02.403 に答える