☝️
【C#】ファイルをアップロードしてS3に保存するWebAPI
はじめに
.NETのWebAPIを開発する際、JSONでやり取りするものはよく作るんですが、ファイルをやり取りするものはどうやって作るんだっけ?となりました。
簡単に検証したので、フロントエンド・バックエンド両方の実装を掲載します。
概要
フロントエンドからバックエンドAPIへ画像をアップロードします。バックエンドではAWSのS3にファイルを保存します。
- フロントエンド
Next.jsで実装しています。axiosを使用してバックエンドAPIへ画像ファイルをPOSTします。 - バックエンド
.NET6で実装しています。フロントエンドから受け取った画像ファイルをS3に保存します。
フロントエンドの実装例
画像ファイルとしてjpegファイル(Blob)を準備しています。canvasに描画した内容をtoBlob
を使用してjpegファイルにしています。
FormData
を作成し、BlobをセットしてPOSTします。
index.tsx
import axios from "axios";
import type { NextPage } from "next";
import { useEffect, useRef } from "react";
const Home: NextPage = () => {
const canvasRef = useRef<HTMLCanvasElement>(null);
// BlobファイルをバックエンドへPostする
const postFile = async (blob: Blob | null) => {
if (blob == null) return;
const form = new FormData();
form.append("upFile", blob);
const res = await axios.post("http://localhost:5217/MyUpload", form);
console.log(res);
};
const handleUpload = async () => {
// canvas画像をjpegに変換 品質90%指定
canvasRef.current?.toBlob((blob) => postFile(blob), "image/jpeg", 0.9);
};
useEffect(() => {
// テスト用画像を準備
const context = canvasRef.current?.getContext("2d");
if (context != null) {
context.fillStyle = "green";
context.fillRect(0, 0, 320, 240);
context.font = "50px Roboto medium";
context.fillStyle = "black";
context.fillText("画像のUpload", 0, 50);
}
}, []);
return (
<>
<canvas ref={canvasRef} width="320" height="240" />
<button onClick={handleUpload}>アップロード</button>
</>
);
};
export default Home;
バックエンドの実装例
Formデータを受信するため、入力モデルに[FromForm]
を指定します。また、ファイルはIFormFile
型を使用します。IFormFile
を使用するとStreamを取得出来たり、ContentTypeを取得出来たり便利です。
S3へのアクセスはAWSSDKを使用しています。
MyUploadController.cs
using Amazon.S3;
using Amazon.S3.Model;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
namespace MyUploadApi.Controllers
{
[ApiController]
[Route("[controller]")]
public class MyUploadController : ControllerBase
{
public MyUploadController(){}
[EnableCors("CorsPolicy")]
[HttpPost(Name = "MyUpload")]
public async Task<UploadOutput> MyUpload([FromForm] UploadInput input)
{
// オブジェクトのキーを生成
var objKey = Guid.NewGuid().ToString("N");
// S3へ保存
var client = new AmazonS3Client();
var response = await client.PutObjectAsync(new PutObjectRequest
{
BucketName = "somebucketname",
Key = objKey,
InputStream = input.UpFile.OpenReadStream(),
ContentType = input.UpFile.ContentType,
});
// S3に保存成功
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
// オブジェクトのキーを返却
return new UploadOutput()
{
Key = objKey,
};
}
// S3に保存失敗
// TODO: エラー原因をログに出したり、フロント側にエラーを伝えること
return new UploadOutput();
}
}
public class UploadInput
{
public IFormFile UpFile { get; set; } = null!;
}
public class UploadOutput
{
public string Key { get; set; } = string.Empty;
}
}
まとめ
ファイルのアップロードをするフロントエンド・バックエンドの実装でした。
どなたかの参考になれば幸いです。
Base64形式でアップロードする方法もあるよ
今回、toBlob
を使用してBlob画像ファイルをPOSTしましたが、toDataURL
を使用してBase64形式の画像をPOSTする方法もあります。
Base64形式に変換すると、画像データは文字列となるためJSONで扱うことができます。JSONとしてGETやPOSTができるため利便性が高いですが、Blobと比べデータサイズが大きくなってしまいます。
ネットワーク・ストレージを節約する観点ではBlob画像ファイルで転送する方がおすすめです。
画像ファイルをS3からダウンロードするWebAPI
ダウンロードするAPIの作り方は下記にまとめています。
Discussion