Angular 2を使用してASP.NETコアWeb APIでリクエストを処理することにより、ファイルのアップロードを実装しています。
私のhtmlコードは次のようになります:
<input #fileInput type="file"/>
<button (click)="addFile()">Add</button>
そしてangular2コード
addFile(): void {
let fi = this.fileInput.nativeElement;
if (fi.files && fi.files[0]) {
let fileToUpload = fi.files[0];
this.documentService
.uploadFile(fileToUpload)
.subscribe(res => {
console.log(res);
});
}
}
そしてサービスは次のようになります
public uploadFile(file: any): Observable<any> {
let input = new FormData();
input.append("file", file, file.name);
let headers = new Headers();
headers.append('Content-Type', 'multipart/form-data');
let options = new RequestOptions({ headers: headers });
return this.http.post(`/api/document/Upload`, input, options);
}
とコントローラコード
[HttpPost]
public async Task Upload(IFormFile file)
{
if (file == null) throw new Exception("File is null");
if (file.Length == 0) throw new Exception("File is empty");
using (Stream stream = file.OpenReadStream())
{
using (var binaryReader = new BinaryReader(stream))
{
var fileContent = binaryReader.ReadBytes((int)file.Length);
//await this.UploadFile(file.ContentDisposition);
}
}
}
私のRequestHeaderは次のようになります
POST /Shell/api/document/Upload HTTP/1.1
Host: localhost:10050
Connection: keep-alive
Content-Length: 2
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJDb3JyZWxhdGlvbklkIjoiZDZlNzE0OTUtZTM2MS00YTkxLWExNWUtNTc5ODY5NjhjNDkxIiwiVXNlcklkIjoiMSIsIlVzZXJOYW1lIjoiWjk5OTkiLCJXb3Jrc3BhY2UiOiJRc3lzVFRAU09BVEVNUCIsIk1hbmRhbnRJZCI6IjUwMDEiLCJDb3N0Q2VudGVySWQiOiIxMDAxIiwiTGFuZ3VhZ2VDb2RlIjoiMSIsIkxhbmd1YWdlU3RyaW5nIjoiZGUtREUiLCJTdGF0aW9uSWQiOiI1NTAwMSIsIk5hbWUiOiJJQlMtU0VSVklDRSIsImlzcyI6InNlbGYiLCJhdWQiOiJodHRwOi8vd3d3LmV4YW1wbGUuY29tIiwiZXhwIjoxNDk1Mzc4Nzg4LCJuYmYiOjE0OTUzNzUxODh9.5ZP7YkEJ2GcWX9ce-kLaWJ79P4d2iCgePKLqMaCe-4A
Origin: http://localhost:10050
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Content-Type: multipart/form-data
Accept: application/json, text/plain, */*
Referer: http://localhost:10050/fmea/1064001/content
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
私が直面している問題は、ファイルがコントローラーで常にnullであることです。
問題を解決するために誰か助けてください。
前もって感謝します。
FormDataで 'multipart/form-data'を使用する必要はありません
Angular 2成分:
<input type="file" class="form-control" name="documents" (change)="onFileChange($event)" />
onFileChange(event: any) {
let fi = event.srcElement;
if (fi.files && fi.files[0]) {
let fileToUpload = fi.files[0];
let formData:FormData = new FormData();
formData.append(fileToUpload.name, fileToUpload);
let headers = new Headers();
headers.append('Accept', 'application/json');
// DON'T SET THE Content-Type to multipart/form-data, You'll get the Missing content-type boundary error
let options = new RequestOptions({ headers: headers });
this.http.post(this.baseUrl + "upload/", formData, options)
.subscribe(r => console.log(r));
}
}
API側
[HttpPost("upload")]
public async Task<IActionResult> Upload()
{
var files = Request.Form.Files;
foreach (var file in files)
{
// to do save
}
return Ok();
}
更新:ASP.NETコアチームからの説明の後、Startup
クラスのcompatスイッチを使用する必要があります。次のように設定した場合:
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
次に、ファイルパラメータから[FromForm]
属性も削除すれば問題ありません。
以前の投稿:私は、最新のASP.NET Core WebApi(この投稿の時点では2.1.2)で同様の問題に遭遇しました。この問題は、1時間のスタックオーバーフロー、調査、多くの試行錯誤の後で偶然に解決できました。私はAngular 6アプリケーションからこのようにファイルを投稿していました:
const formData: FormData = new FormData();
formData.append('file', file, file.name);
const req = new HttpRequest('POST', 'upload-url', formData, {
reportProgress: true
});
this.http.request(req).subscribe(...) // omitted the rest
問題は、IFormFile file
を前に置いても、[FromForm]
アクションメソッドパラメータが常にnull
であったことです。 ASP.NET Core 2.1でのAPIコントローラーの動作の変更により、[FromForm]
が必要になりました。[FromBody]
がAPIコントローラーのデフォルトになります。奇妙なことに、それでも機能しませんでした。値はnull
のままでした。
最後に、次のように、属性を使用してフォームコンテンツパラメーターの名前を明示的に宣言することで解決しました。
public async Task<IActionResult> UploadLogo([FromForm(Name = "file")] IFormFile file)
{
...
}
これで、ファイルのアップロードがコントローラーパラメーターに正しくバインドされました。それが私の正気をほとんど失ってしまったので、これが将来誰かを助けるかもしれないことを願っています:D
Dotnetコアの別の方法として、デフォルトのヘッダーを設定して、IFormFileインターフェイスを使用できます。
角度2
let formData = new FormData();
formData.append("file", yourUploadFile);
this.http.post("your_api_path", formData).subscribe(r => console.log(r));
ドットネットコア
[HttpPost]
[Route("/your_api_path")]
public async Task<IActionResult> Upload(IFormFile file) {
//...next awaiters...
}
複数のファイルを送信する場合は、ICollection<IFormFile>
をアップロードパラメータとして使用できます。
複数のプロパティを送信する場合、カスタムモデルオブジェクトを使用でき、IFormFileはプロパティの1つになります。
お役に立てれば幸いです。