ファイルの保存を処理するWeb APIを作成しようとしています。
Asp.Netコア1.0+フレームワークには、ファイルをビューモデルにバインドできる IFormFile インターフェースが付属しています。 ASP.NET Coreでのファイルのアップロードに関するドキュメント は次のように述べています
IFormFileは、アクションメソッドパラメータまたはバインドされたモデルプロパティとして直接使用できます。
アクションメソッドのパラメーターとしてIFormFile
を使用したところ、問題なく動作しました。しかし、私の場合は、カスタム検証ルールを含めることに加えて他の値をバインドしたいので、モデルのプロパティとして使用したいと思います。これが私のビューモデルです。
public class NewFile
{
[Required]
[MinFileSize(125), MaxFileSize(5 * 1024 * 1024)]
[AllowedExtensions(new[] { ".jpg", ".png", ".gif", ".jpeg", ".tiff" })]
public IFormFile File { get; set; }
[Required]
public int? CustomField1 { get; set; }
[Required]
public int? CustomField2 { get; set; }
[Required]
public int? CustomField3 { get; set; }
}
クライアント要求と、ファイルを受け入れるサーバーコードの両方のコードは次のとおりです。簡単にするために、どちらの方法も同じコントローラに配置されています。しかし実際には、「クライアント」メソッドは、ファイルを送信する別のアプリケーションに配置されます。
[ApiController, Route("api/[controller]")]
public class FilesController : ControllerBase
{
[HttpGet("client")]
public async Task<IActionResult> Client()
{
using HttpClient client = new HttpClient();
// we need to send a request with multipart/form-data
var multiForm = new MultipartFormDataContent
{
// add API method parameters
{ new StringContent("CustomField1"), "1" },
{ new StringContent("CustomField2"), "1234" },
{ new StringContent("CustomField3"), "5" },
};
// add file and directly upload it
using FileStream fs = System.IO.File.OpenRead("C:/1.jpg");
multiForm.Add(new StreamContent(fs), "file", "1.jpg");
// send request to API
var responce = await client.PostAsync("https://localhost:123/api/files/store", multiForm);
return Content("Done");
}
[HttpPost("store")]
public async Task<IActionResult> Store(NewFile model)
{
if (ModelState.IsValid)
{
try
{
var filename = MakeFileName(model, Path.GetFileName(model.File.FileName));
Directory.CreateDirectory(Path.GetDirectoryName(filename));
using var stream = new FileStream(filename, FileMode.Create);
await model.File.CopyToAsync(stream);
return PhysicalFile(filename, "application/octet-stream");
}
catch (Exception e)
{
return Problem(e.Message);
}
}
// Are there a better way to display validation errors when using Web API?
var errors = string.Join("; ", ModelState.Values.SelectMany(v => v.Errors).Select(v => v.ErrorMessage));
return Problem(errors);
}
}
リクエストを行うと、次のエラーが表示されますが、ブレークポイントをそこに配置したため、リクエストがstore
メソッドに到達することはありませんが、そこに到達することはありません。
StatusCode:415、ReasonPhrase: 'Unsupported Media Type'、バージョン:1.1、コンテンツ:System.Net.Http.HttpConnectionResponseContent
ファイルをサーバーに正しく送信し、ビューモデルのFile
プロパティにバインドさせるにはどうすればよいですか?
ApiController
は、明示的に指示されない限り、デフォルトでJSONを期待します
使用する - [FromForm]
リクエストの本文でフォームデータを使用してモデルをバインドします。
public async Task<IActionResult> Store([FromForm]NewFile model) {
//...
}.
リファレンス ASP.NET Coreのモデルバインディング
customField1、CustomField2、およびCustomField3`は、元の質問にあるように一緒に送信されているにもかかわらず、nullです
クライアントはこれらの他のフィールドを正しく送信していません。コンテンツとフィールド名を切り替えました
var multiForm = new MultipartFormDataContent {
// add API method parameters
{ new StringContent("1"), "CustomField1" },
{ new StringContent("1234"), "CustomField2" },
{ new StringContent("5"), "CustomField3" },
};