はじめに
こんにちは。S.Sです。
今回はC#(ASP.NET)で、multipart/form-dataを用いたファイルアップロード機能を実装することになり、受信したファイルをフォルダに保存する際、アップロードされたファイル名が一時ファイル名になってしまい、元のファイル名で保存するための処理の作成に時間がかかってしまったので、備忘録を兼ねて記します。
ファイルアップロード処理を作成する
ファイルのアップロード実装自体は公式が参考ページを用意してくれていましたのですんなり実装できました。(こちら)
MultipartFormDataStreamProviderクラスのインスタンスを作成し、
await Request.Content.ReadAsMultipartAsync() とすることで実装ができるようです。
string path = ("任意のアップロード先フォルダー")
var provider = new MultipartFormDataStreamProvider(path);
await Request.Content.ReadAsMultipartAsync(provider);
アップロードされたファイル名が一時ファイル名として保存されている
上記でファイルアップロードを実装し、実際にPostmanでform-dataでファイルを送信してみたところ「BodyPart_……」のようなファイル名で保存されていました。
provider.FileDataから一時ファイル名とオリジナルのファイル名を取得し、任意のフォルダにコピーすればいいようなのですが、最初から元のファイル名で保存されるようにできないかな~…。と思いもう少し調べました。
MultipartFormDataStreamProviderを継承したクラスを作成する
(こちら)が参考になりました。
ReadAsMultipartAsyncでファイル読み込み完了時に呼び出されるMultipartFormDataStreamProviderクラスのGetLocalFileNameという処理をオーバーライドして、オリジナルのファイル名をReturnするようにすれば良い。ということのようです。
/// MultipartFormDataStreamProviderを継承したカスタムクラス
class MyMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
/// コンストラクタ
public MyMultipartFormDataStreamprovider(string path):base(path)
{ }
/// ファイル読み込み完了時呼び出される処理をオーバーライド
public override string GetLocalFileName(System.Net.http.Headers.HttpContentHeaders headers)
{
return headers.ContentDisposition.FileName.Trim('\"');
}
}
上記で作成したカスタムクラスのインスタンスを作成し、await Request.Content.ReadAsMultipartAsync()とすることで
string path = ("任意のアップロード先フォルダー")
var provider = new MyMultipartFormDataStreamProvider(path); // GetLocalFileNameをオーバーライドしたカスタムクラス
await Request.Content.ReadAsMultipartAsync(provider);
元のファイル名で保存することができました。
書いてみたらこれだけか。。という感じですが、これで元のファイル名で保存することができ、目的達成です。☺