フォームから大容量ファイルをアップロードする
ファイルアップロード機能付きの問い合わせフォーム作成のご依頼をいただくことがあります。
フォームからファイルをアップロードする場合に厄介なのは、リクエストサイズの上限設定でしょう。
PHPならmemory_limit, post_max_size, upload_max_filesizeの制限に引っかかることがよくあります。WebサーバーレベルではApacheならLimitRequestBody、Nginxならclient_max_body_sizeのような設定があります。
単純に <input type="file" /> 要素を使ってファイルをサーバーに送信する方法では、1MB程度までのファイルのアップロードならそれほど問題になることはありませんが、数百MB~GBクラスのファイルをアップロードする場合は、まず上記の上限設定に引っかかることになります。この場合、サーバーの設定を変更できるなら変更するのも手ですが、サーバー側の都合(契約しているプランとか)で、あまり大きい値に変更できない場合もあります。あまり極端に設定値を大きくして、メモリを浪費されても困りますしね。
これらのサイズ制限がある中で、大容量のファイルをアップロードするには、<input type="file" />ではなく、JavaScriptでアップロード処理を作成します。 アップロード処理を作成するといっても、XMLHttpRequestを直接使って実装するような人は、、、まずいないでしょう、通常はaxios等のライブラリを使ってアップロードすることになります。
axiosを使ったアップロードの例
const formData = new FormData(); formData.append('file', file); // file is File object result = await axios.post( url, formData, { headers: { 'Content-Type': 'multipart/form-data' }, });
といっても、上記のようにFileオブジェクトをそのままアップロードしてしまっては、結局、上限設定に引っかかります。それではどうするかというと、Fileクラスにはslice()メソッドというものがあり、ファイルデータを分割したBlobにすることができます。
https://developer.mozilla.org/ja/docs/Web/API/Blob/slice
FileのBlobへの分割
const blob = file.slice(start, end);
これを使って、Fileを複数のBlobに分割して、複数リクエストに分けてアップロードすることで、サイズ上限設定を回避しつつ大きいファイルをアップロードできるようになります。
FileをBlobに分割してアップロード
for (let i = 0 ; i < sliceN ; i++) { const start = sliceSize * i; const end = Math.min(start + sliceSize, file.size); const blob = file.slice(start, end); const formData = new FormData(); formData.append('blob', blob); result = await axios.post( url, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); }
上記のコードはあくまでイメージなので注意してください。実用とするには、サーバー側でファイルを結合できるようにするため、アップロードファイルを識別するためのIDのようなものを送ったり、送信データが何番目のBlobなのかを示す情報を送ったりと、他にも色々行うべきことがあります。
また、ここまではクライアント側の話ですが、サーバー側でも色々作業が必要になります。
- 分割して送られたファイルの結合処理
結合処理においても、メモリを浪費して制限値を越えないように注意して実装する必要がある。 - ファイルを分割したり結合したりするので、念のためクライアントとサーバーでそれぞれダイジェスト値を計算して比較する
等々。
以上のようにBlobに分割してアップロードすれば、制限が低めのサーバーでも大容量のファイルをアップロードすることができます。
以下は宣伝です。
いつもご依頼を頂くのはファイルサイズは1MBとかメール添付できる程度のもので、それらはもっと単純な作りですが、それでも、いたずらで大量のファイルをアップロードされたりしないように、IPアドレスごとにアップロードのrate limitをかけたりと色々気をつけて実装しています。
アップロード機能付きの問い合わせフォームをお探しでしたら、お気軽にお問い合わせください。
ある程度大きいファイルのアップロードに対応した問い合わせフォームを作成することも可能です。ただ、ギガバイトクラスのファイルのアップロードを安定的に運用したいのなら外部サービスを使った方が楽だとは思います。
お客様と入稿データ、納品データ等の大容量ファイルをやりとりしたい場合は、ファイルシェアツール NoPPAPを提供しています。

NoPPAPではこのようなWeb管理画面を通して、お客様と大容量のファイルのやりとりが可能です。メールでのファイルのやりとりが煩雑で困っている。ファイルが大きすぎてお客様とのやりとりが大変、といったことにお困りでしたらお気軽にご相談ください。
投稿日:2023/01/14 23:05
タグ: Server PHP JavaScript