単一の画像ファイルをアップロードしようとしていました。サンプルコードは次のとおりです。
/// <summary>
/// Uploads a single image document
/// </summary>
/// <returns></returns>
[HttpPost]
[Route("{id}/scan-doc-image")]
//[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]
public async Task<ActionResult> UploadImage(int id, IFormFile file)
{
// more validation goes here.
if (file == null)
{
return BadRequest();
}
// save image if any
if (file.Length > 0)
{
var uploads = Path.Combine(_envirnment.WebRootPath, "uploads");
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
return Ok();
}
これが私が気づいたことです:
この API を呼び出すと、サービスが自動的に停止します。何度も試しましたが、いつもシャットダウンしてしまいます。他の API 呼び出しを行ってもサービスは停止しませんでした。参考まで
POSTMAN からも電話をかけてみました。今回はサービスは終了しませんでしたが、「リクエスト フォームの読み取りに失敗しました」というエラーが発生し続けます。コンテンツ タイプの境界がありません。
Content-Type を multipart/form-data として指定していることに注意してください。また、境界を max より小さい数値で指定しても、やはりエラーが発生します。上記の RequestFormLimit 属性のコメントを解除しても、役に立ちませんでした。
それでは、ここで何が欠けているのでしょうか?単一の画像をアップロードするのに必要なものはすべてファイル。
------------------------
POSTMAN からも電話をかけてみました。今回は閉まらなかった
サービスを利用できましたが、エラーが発生し続けます: リクエストの読み取りに失敗しました
形状。コンテンツ タイプの境界がありません。私が指定していることに注意してください
Content-Type は multipart/form-data です。そして、境界を指定すると、
数値が最大値より小さい場合でも、エラーは発生します。コメントを解除した場合でも、
上記の RequestFormLimit 属性も役に立ちませんでした。
Content-Type ヘッダーを手動で追加する必要はありません。 Postman によって設定された値を上書きしています。 POST リクエストで form-data を選択し、リクエストを送信して、それが機能するかどうかを確認するだけです。設定する必要はありませんフォームデータが投稿されるときのヘッダー。 Content-Type を削除して、以下のようにアップロードするだけです。
エラーが発生する可能性のあるパスについての注意事項
Web API プロジェクトを使用している場合は、_envirnment.WebRootPath に null が返されます。 Web API プロジェクトに wwww ディレクトリがありません。
解決
WebRootPath を変更する
var uploads = Path.Combine(_envirnment.WebRootPath, "uploads");
ContentRootPath へ
var uploads = Path.Combine(_envirnment.ContentRootPath, "uploads");
テスト
コントローラのコード
指定したフォルダーが「アップロード」された場合、存在しません。最初に作成してから、このフォルダーにファイルを保存します。フォルダーがすでに存在する場合は、そのフォルダーにファイルを保存するだけです。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace WebAPIDemos.Controllers
{
[ApiController]
[Route("[controller]")]
public class FileController : ControllerBase
{
private readonly IWebHostEnvironment _envirnment;
public FileController(IWebHostEnvironment appEnvironment)
{
_envirnment = appEnvironment;
}
[HttpPost]
[Route("{id}/scan-doc-image")]
//[RequestFormLimits(ValueLengthLimit = int.MaxValue, MultipartBodyLengthLimit = int.MaxValue)]
public async Task<ActionResult> UploadImage(int id, IFormFile file)
{
// more validation goes here.
if (file == null)
{
return BadRequest();
}
// save image if any
if (file.Length > 0)
{
//var uploads = Path.Combine(_envirnment.WebRootPath, "uploads");
var uploads = Path.Combine(_envirnment.ContentRootPath, "uploads");
var destinationDirectory = new DirectoryInfo(uploads);
if (!destinationDirectory.Exists)
destinationDirectory.Create();
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
return Ok();
}
}
}
2
@Lightman に感謝します。content-type を指定しないと役に立ちます。ただし、デバッグすると、大きな境界番号を持つ Content-Type: multipart/form-data が依然として郵便配達員によって送信されていることがわかります。つまり、実際にはコンテンツタイプが間違っていたわけではありませんが、どういうわけか、郵便配達員が送信して指定したものだけを使用した場合でも、機能しませんでした。画像をアップロードしようとすると、Swagger は依然としてアプリを閉じます。ルート フォルダーは別の理由で存在し、正常に動作します。
– コレフ コレフ
2020 年 9 月 4 日 11:21
ペイロードが生のファイルの内容だけであるアップロードは、マルチパート/フォームデータではないため、Swagger 2.0 ではサポートされません。こんにちは、@Koref 、PUT 経由でファイルをアップロードできますか? swagger.ioより。お役に立てば幸いです。
– マイケル・ワン
2020 年 9 月 7 日 8:09