ASP.NET Web Api Self Host大ファイルアップロード機能
11443 ワード
今日は同僚がASPを使っています.NET WebApiがファイルアップロード機能を開発したところ、WebApiが大きなファイルアップロード機能を実現できないことに気づき、助けを求めました.
私がこの問題を知ったとき、最初の反応はWebApiがサポートしないはずがないので、彼のコードを見始めました.
View Code
次の問題が発生しました.
1.MaxReceivedMessageSizeは、より大きな値に変更されていません.デフォルトは65536です.受信メッセージがこの値を超えると、サーバは受信を終了します.
2.転送モードが変更されていないことを発見した.すなわち、TransferModeである.TransferModeには2つのモードがあり、1つはBufferモードであり、Bufferモードはファイルをバッファに受信し、ファイルの完全な受信が完了するまでプログラムに処理されない.
アップロードされたファイルのサイズがBufferよりも大きい場合、ファイルの受信が完了していないバッファがいっぱいになっているため、異常が発生します.TransferModeのStreamモードはこの問題を解決し、StreamはBufferモードとは異なり、Streamモードはファイルをサポートする
受信しながら保存することで、大きなファイル転送の問題を解決できます.
しかし、そのBufferモードは何の役に立つのかと聞かれます.実はBufferモードにもその応用シーンがあり、一般的に信頼性の高い伝送に用いられている.すなわち、すべて受信しないか、受信しないか.WSの信頼性の高い伝送はこのように実現されたと推測される.
修正後のコード:
View Code
コード修正後の大きなファイルの受信は成功したが、受信後のファイルが開くことができなかったり、フォーマットが間違っていたりする問題を発見し、同僚が開発したクライアントを表示するには、WebClientを使用する.UploadFileメソッドでファイルをアップロードする場合、UploadメソッドではPostメソッドを使用してアップロードするため、Filddlerを使用してファイルアップロード要求をシミュレートし、Postメソッドを使用してファイルをアップロードする場合、Http Request Bodyにセパレータクラスの文字がいくつか存在することを発見します.
Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468User-Agent: Fiddler
---------------------------acebdf13572468Content-Disposition: form-data; name="fieldNameHere"; filename="IMG_2116.JPG"Content-Type: image/jpeg
<@INCLUDE *C:\Users\kuangfenlin\Desktop\IMG_2116.JPG*@>---------------------------acebdf13572468--
Googleによると、これは実際には複数のファイルを同時にアップロードする基準であり、複数のファイルまたはコンテンツはboundary=------------------------------acebdf 13572468によって分割されている.
これにより、ファイル受信後に開くことができない理由が説明され、WebApiソースコードを確認すると、M u l t i p artFormDataStreamProviderタイプがこのような状況を処理するために使用されていることがわかり、Actionコードを変更します.
View Code
へへへ、もう完璧にこの問題を解決しました!
私がこの問題を知ったとき、最初の反応はWebApiがサポートしないはずがないので、彼のコードを見始めました.
View Code
1 var config = new HttpSelfHostConfiguration("http://localhost:8080");
2
3 config.Routes.MapHttpRoute(
4 name: "DefaultApi",
5 routeTemplate: "api/{controller}/{action}"
6 );
7
8 HttpSelfHostServer server = new HttpSelfHostServer(config);
9
10 server.OpenAsync().Wait();
11
12 Console.WriteLine("Server Started..");
次の問題が発生しました.
1.MaxReceivedMessageSizeは、より大きな値に変更されていません.デフォルトは65536です.受信メッセージがこの値を超えると、サーバは受信を終了します.
2.転送モードが変更されていないことを発見した.すなわち、TransferModeである.TransferModeには2つのモードがあり、1つはBufferモードであり、Bufferモードはファイルをバッファに受信し、ファイルの完全な受信が完了するまでプログラムに処理されない.
アップロードされたファイルのサイズがBufferよりも大きい場合、ファイルの受信が完了していないバッファがいっぱいになっているため、異常が発生します.TransferModeのStreamモードはこの問題を解決し、StreamはBufferモードとは異なり、Streamモードはファイルをサポートする
受信しながら保存することで、大きなファイル転送の問題を解決できます.
しかし、そのBufferモードは何の役に立つのかと聞かれます.実はBufferモードにもその応用シーンがあり、一般的に信頼性の高い伝送に用いられている.すなわち、すべて受信しないか、受信しないか.WSの信頼性の高い伝送はこのように実現されたと推測される.
修正後のコード:
View Code
1 var config = new HttpSelfHostConfiguration("http://localhost:8080");
2
3 //
4 config.MaxReceivedMessageSize = int.MaxValue;
5 // , ,
6 config.TransferMode = TransferMode.Buffered;
7
8 config.Routes.MapHttpRoute(
9 name: "DefaultApi",
10 routeTemplate: "api/{controller}/{action}"
11 );
12
13 HttpSelfHostServer server = new HttpSelfHostServer(config);
14
15 server.OpenAsync().Wait();
16
17 Console.WriteLine("Server Started..");
コード修正後の大きなファイルの受信は成功したが、受信後のファイルが開くことができなかったり、フォーマットが間違っていたりする問題を発見し、同僚が開発したクライアントを表示するには、WebClientを使用する.UploadFileメソッドでファイルをアップロードする場合、UploadメソッドではPostメソッドを使用してアップロードするため、Filddlerを使用してファイルアップロード要求をシミュレートし、Postメソッドを使用してファイルをアップロードする場合、Http Request Bodyにセパレータクラスの文字がいくつか存在することを発見します.
Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468User-Agent: Fiddler
---------------------------acebdf13572468Content-Disposition: form-data; name="fieldNameHere"; filename="IMG_2116.JPG"Content-Type: image/jpeg
<@INCLUDE *C:\Users\kuangfenlin\Desktop\IMG_2116.JPG*@>---------------------------acebdf13572468--
Googleによると、これは実際には複数のファイルを同時にアップロードする基準であり、複数のファイルまたはコンテンツはboundary=------------------------------acebdf 13572468によって分割されている.
これにより、ファイル受信後に開くことができない理由が説明され、WebApiソースコードを確認すると、M u l t i p artFormDataStreamProviderタイプがこのような状況を処理するために使用されていることがわかり、Actionコードを変更します.
View Code
1 if (!Request.Content.IsMimeMultipartContent())
2 {
3 throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
4 }
5
6 string root = @"C:/";
7 var provider = new MultipartFormDataStreamProvider(root);
8
9 try
10 {
11 StringBuilder sb = new StringBuilder();
12
13 var task = Request.Content.ReadAsMultipartAsync(provider);
14
15 task.Wait();
16
17 foreach (var file in provider.FileData)
18 {
19 FileInfo fileInfo = new FileInfo(file.LocalFileName);
20 sb.Append(string.Format("Uploaded file: {0} ({1} bytes)
", fileInfo.Name, fileInfo.Length));
21 }
22 return new HttpResponseMessage()
23 {
24 Content = new StringContent(sb.ToString())
25 };
26 }
27 catch (System.Exception e)
28 {
29 return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
30 }
へへへ、もう完璧にこの問題を解決しました!