- Published on
ファイルアップロード & ストレージツール 2026 — Uppy / UploadThing / Pinata IPFS / Cloudflare R2 / Backblaze B2 / Tigris / MinIO / tus protocol 徹底ガイド
- Authors

- Name
- Youngju Kim
- @fjvbn20031
「ファイルを受け取って保存するという作業はシンプルに見えるが、1GBの動画が30回のリトライで落ちた瞬間にすべての抽象化が崩壊する。2026年のファイルアップロードはもはやmultipart/form-dataではない。」 — Transloadit Uppyチーム、2024年12月インタビュー
ファイルアップロードはほぼすべてのサービスで必要な機能でありながら、本番でもっとも頻繁に壊れる機能のひとつでもあります。LTE回線で1GBの動画を上げているユーザーが99%でWi-Fiを失うと、また最初からやり直しになります。100人が同時にPDFを送ってくるとNodeプロセスがOOMで死にます。そして必ず誰かが.exeやZIP爆弾を投げてきます。
2026年5月現在、ファイルアップロードとオブジェクトストレージのエコシステムは クライアントライブラリ(Client)、マネージドSaaS(Managed)、セルフホストOSS(Self-hosted)、分散ストレージ(Decentralized) の4カテゴリにきれいに分かれており、その上に再開可能アップロードのデファクトスタンダードとしてtusプロトコルが定着しています。この記事ではUppy、UploadThing、Filestack、Cloudinary、ImageKit、AWS S3 Presigned URLs、Cloudflare R2、Backblaze B2、Tigris、Wasabi、Vercel Blob、Bunny Storage、MinIO、SeaweedFS、Garage、Pinata、Filebase、Storj DCS、Arweave、tus、ClamAV、Sublime Securityを一度に整理します。
1. 2026年のファイルアップロード地図 — 4分類
ファイルアップロードのインフラは役割によって4つの箱に分けられます。
| カテゴリ | 代表プロダクト | 役割 |
|---|---|---|
| Clientライブラリ | Uppy、UploadThing、Filestack JS、Cloudinary Widget、ImageKit JS | ブラウザ/モバイルでチャンキング、リトライ、UIを担当 |
| Managed SaaS | UploadThing、Filestack、Cloudinary、ImageKit、Vercel Blob、Bunny | API一行でアップロード + CDN + 変換 |
| S3互換 / Self-hosted | AWS S3、Cloudflare R2、Backblaze B2、Wasabi、Tigris、MinIO、SeaweedFS、Garage | オブジェクトストレージのインフラ |
| Decentralized | Pinata、Filebase、Storj DCS、Arweave | IPFS、Sia、Filecoin、Arweave上の永久・分散保存 |
この分類が重要なのは、「どこに保存するか(Storage)」と「どう運ぶか(Transport)」が独立した選択だからです。クライアントのUppyはS3 Presigned URLにもCloudflare R2にもMinIOにも、さらにはPinata IPFSにも送れます。UploadThingのようなフルスタックSaaSは両方をまとめて売っていますが、内部はやはりTransport + Storageの組み合わせです。
もうひとつの分岐点が エグレス(Egress)の料金モデル です。AWS S3は外向き転送に1GBあたり約0.09 USDを取りますが、Cloudflare R2とBackblaze B2は実質0 USDです。動画や画像のようにCDNから常時出ていくコンテンツがメインのワークロードでは、この差が月に数千ドル規模に膨らみます。
2026年のもうひとつのキーワードが resumable(再開可能) です。tusプロトコルが2024年にIETFのInternet-Draftを通過し事実上の標準になっており、Uppy、UploadThing、Vercel Blob、Cloudflare R2はいずれもtusを一級でサポートします。99%まで上がった1GBファイルがWi-Fi切断で落ちても、次にWi-Fiが入った瞬間に99%から続きを送れるという意味です。
2. Uppy (Transloadit) — もっとも人気のOSSアップローダー
Uppy(uppy.io)はTransloaditが2017年にオープンソース公開したモジュール型ファイルアップローダーです。2026年5月現在GitHubスター30k超で、クライアントサイドアップローダーのカテゴリでは事実上の標準です。
中心思想は「プラグインアーキテクチャ」です。コア本体は1MB未満で、必要な機能だけプラグインを足していきます。
// React + Uppy + tus + S3 + Webカメラ + Instagram
import Uppy from '@uppy/core'
import Dashboard from '@uppy/dashboard'
import Tus from '@uppy/tus'
import AwsS3 from '@uppy/aws-s3'
import Webcam from '@uppy/webcam'
import Instagram from '@uppy/instagram'
const uppy = new Uppy({
restrictions: {
maxFileSize: 1024 * 1024 * 1024, // 1GB
maxNumberOfFiles: 10,
allowedFileTypes: ['image/*', 'video/*', '.pdf', '.zip'],
},
autoProceed: false,
})
.use(Dashboard, { inline: true, target: '#drag-drop' })
.use(Webcam, { target: Dashboard })
.use(Instagram, { companionUrl: 'https://companion.acme.dev' })
.use(Tus, {
endpoint: 'https://uploads.acme.dev/files/',
chunkSize: 5 * 1024 * 1024, // 5MBチャンク
retryDelays: [0, 1000, 3000, 5000],
})
この一塊だけでドラッグアンドドロップUI、進捗バー、一時停止/再開、チャンクアップロード、リトライ、Webカメラ撮影、Instagramインポートまでが揃います。同じコードに@uppy/google-drive、@uppy/dropbox、@uppy/onedriveを足せばクラウドインポートも入ります。
サーバー側のペアが Companion(@uppy/companion)で、ユーザーのGoogle Drive/DropboxからOAuthでトークンを受け、ブラウザを経由せず直接サーバー間でS3へ転送します。大きなリモートファイルを「ブラウザでダウンロードしてから再アップロード」する無駄を消してくれます。
2025年5月リリースの Uppy 4.0 はTypeScriptを一級にした書き直しで、React/Vue/Svelte用の公式アダプタが同梱されました。同年11月にはTransloaditのマネージド変換バックエンド(@uppy/transloadit)との統合が強化され、アップロード直後に動画トランスコード、画像リサイズ、ウイルススキャンを一本のパイプラインで走らせられます。
Uppyが向いているのは 自社のバックエンドとストレージをすでに持っているチームがクライアントUXだけ素早く整えたい場面 です。UploadThingのようなフルスタックを丸ごと買うのは重すぎ、自前でmultipartを書きたくもない、ちょうどその中間に落ちます。
3. UploadThing — Vercel親和、TypeScript優先
UploadThing(uploadthing.com)はTheo Browne(t3.gg)が2023年に作り、2024年にY Combinatorに合流、2025年にシリーズAを調達したTypeScript優先のアップロードSaaSです。Vercelエコシステムでもっとも成長の早いストレージ製品です。
差別化は 「Next.jsとのゼロコンフィグ統合」 と 「型安全なファイルルーター」 です。
// app/api/uploadthing/core.ts
import { createUploadthing, type FileRouter } from 'uploadthing/next'
import { auth } from '@/auth'
const f = createUploadthing()
export const ourFileRouter = {
imageUploader: f({ image: { maxFileSize: '4MB', maxFileCount: 4 } })
.middleware(async ({ req }) => {
const session = await auth()
if (!session?.user) throw new Error('Unauthorized')
return { userId: session.user.id }
})
.onUploadComplete(async ({ metadata, file }) => {
await db.media.create({
data: { userId: metadata.userId, url: file.url, key: file.key },
})
}),
pdfUploader: f({ pdf: { maxFileSize: '32MB' } })
.middleware(async () => ({ userId: 'pdf-user' }))
.onUploadComplete(async ({ file }) => {
console.log('PDF uploaded:', file.url)
}),
} satisfies FileRouter
export type OurFileRouter = typeof ourFileRouter
クライアント側は<UploadButton endpoint="imageUploader" />一行で済みます。ルーターの型がそのままコンポーネントに流れ込むので、エンドポイント名を打ち間違えるとTypeScriptが弾いてくれます。
UploadThingのバックエンドは元々AWS S3 + Cloudflare上に自前で構築されていましたが、2025年からはBYOS(Bring Your Own Storage)もサポートします。R2、S3、Vercel Blobの中から好きな先に送れて、変換パイプラインはそのまま使えます。
2026年1月に追加された UTApi はサーバーから直接ファイルを操作するAPIで、削除、メタデータ更新、署名付きURLをSDK一行で扱えます。
import { UTApi } from 'uploadthing/server'
const utapi = new UTApi()
await utapi.deleteFiles(['key1', 'key2'])
await utapi.getFileUrls(['key1']) // 一時的な署名URL
UploadThingがハマるのは Next.js + Vercel + Auth.jsスタックの個人〜小規模チーム です。Stripeの「5分で決済を組み込む」と同じノリで「5分でアップロードを組み込む」を狙っています。
4. Filestack / Cloudinary / ImageKit — マネージドメディア
マネージドメディアのカテゴリはアップロード + CDN + 変換を一括で売る市場で、3社が約13年競い合っています。
Filestack(filestack.com)は2012年創業のもっとも古いプレイヤーで、2019年にIderaに買収されました。強みは 40を超える外部ソース(Facebook、Instagram、Box、Dropbox、OneDriveなど)から直接インポートできるPickerウィジェットと、画像・文書・動画をひとつのAPIで扱えるTransformation Engineです。
<script src="//static.filestackapi.com/filestack-js/3.x.x/filestack.min.js"></script>
<script>
const client = filestack.init('YOUR_API_KEY')
client.picker({
accept: ['image/*', 'application/pdf'],
fromSources: ['local_file_system', 'instagram', 'gmail', 'webcam'],
maxFiles: 5,
transformations: { crop: { aspectRatio: 1 / 1, force: true } },
}).open()
</script>
Cloudinary(cloudinary.com)は2012年にイスラエルで始まったメディア特化SaaSで、2026年時点では最大のマネージドメディア事業者です。URLベースの画像・動画変換が核です。たとえばhttps://res.cloudinary.com/demo/image/upload/w_300,h_300,c_fill,f_auto,q_auto/sample.jpgのようなURLにすると自動でWebP/AVIFエンコード、クロップ、キャッシュ、CDN配信までしてくれます。
アップロードウィジェット(cloudinary.openUploadWidget)は外部ソース14個とWebカメラ・スクリーンショット撮影に対応し、2024年以降はAIによる自動タグ付け、自動クロッピング(c_auto)、背景除去が標準装備されました。
ImageKit(imagekit.io)は2017年にインドで始まった後発で、価格と性能を武器に急成長しています。Cloudinaryに似たURL変換APIを約3分の1の価格で提供し、AWS S3、R2、Backblazeなどの外部ストレージをoriginとして接続(BYOS)できる点が特徴です。直接アップロード(imagekit.upload(...))とサーバー側トークン発行の両方をサポートします。
3製品の比較:
| 製品 | 強み | 弱み | 価格 |
|---|---|---|---|
| Filestack | 外部ソース最多、文書変換 | 高くて重い | 月額99 USDから |
| Cloudinary | 画像・動画変換の深さ、AI機能 | 価格、学習コスト | 無料25クレジット、以後従量 |
| ImageKit | BYOS、コスト効率 | 変換の深さがやや浅い | 無料20GB、以後従量 |
5. AWS S3 Presigned URLs — DIYの古典
もっとも古く、そして今でもっとも一般的なパターンが AWS S3 Presigned URL です。2006年のS3リリース以来ほぼそのままで、サーバーが一時的な署名付きPUT URLを発行し、ブラウザがそのURLにPUTを直接投げます。
// サーバー: Next.js Route Handler
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
const s3 = new S3Client({ region: 'ap-northeast-1' })
export async function POST(req: Request) {
const { filename, contentType } = await req.json()
const key = `uploads/${Date.now()}-${filename}`
const command = new PutObjectCommand({
Bucket: 'acme-uploads',
Key: key,
ContentType: contentType,
})
const url = await getSignedUrl(s3, command, { expiresIn: 60 * 5 })
return Response.json({ url, key })
}
// クライアント
async function upload(file: File) {
const res = await fetch('/api/presign', {
method: 'POST',
body: JSON.stringify({ filename: file.name, contentType: file.type }),
})
const { url, key } = await res.json()
await fetch(url, {
method: 'PUT',
headers: { 'Content-Type': file.type },
body: file,
})
return key
}
このパターンの強みは サーバーを経由しない ことです。5GBのファイルでもNext.jsサーバーのメモリも帯域も0で、全負荷がそのままS3に流れます。認証・検証・ロギングは署名発行のステップだけで完結します。
弱みは リトライと進捗を自分で書く必要がある ことです。fetch APIはアップロードの進捗イベントを出さないので、XMLHttpRequestやaxiosのonUploadProgressを使うことになり、5GBを超えると Multipart Upload が強制されます。実務ではほぼ常にUppyの@uppy/aws-s3-multipartプラグインと組み合わせて使われます。
同じパターンはCloudflare R2、Backblaze B2、Wasabi、MinIO、Tigrisでもそのまま動きます。「S3 APIに準拠する」という一行が、オブジェクトストレージ市場全体を標準化した結果です。
6. Cloudflare R2 — エグレス無料
Cloudflare R2(developers.cloudflare.com/r2)は2022年にGAしたS3互換のオブジェクトストレージで、たったひとつのマーケティングメッセージで市場を揺らしました。「エグレス(外向き転送)料金0 USD」です。
AWS S3で月に1TBの画像を配信すると約90 USDの転送料が発生しますが、R2では0 USDです。ストレージ料金もGB単価0.015 USDで、S3の0.023 USDより35%安い計算です。
// R2はS3 SDKをそのまま使える
import { S3Client } from '@aws-sdk/client-s3'
const r2 = new S3Client({
region: 'auto',
endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY!,
secretAccessKey: process.env.R2_SECRET_KEY!,
},
})
R2の本当の強みは Cloudflare Workers・Pages・グローバルCDNとの統合 です。R2バケットをWorkersにバインドすれば、SDKなしでenv.MY_BUCKET.put(key, body)と書くだけで読み書きでき、同じグローバルネットワーク上で動きます。
// Cloudflare Workers + R2
export default {
async fetch(req: Request, env: Env) {
const key = new URL(req.url).pathname.slice(1)
if (req.method === 'PUT') {
await env.MY_BUCKET.put(key, req.body, {
httpMetadata: { contentType: req.headers.get('content-type') ?? '' },
})
return new Response('ok')
}
const obj = await env.MY_BUCKET.get(key)
if (!obj) return new Response('not found', { status: 404 })
return new Response(obj.body, { headers: { 'content-type': obj.httpMetadata?.contentType ?? '' } })
},
}
2024年に追加された R2 Custom Domain + Cache Reserve はR2オブジェクトを自動でCloudflare CDNにキャッシュするので、初回以外はR2のGET料金すらかかりません。2025年リリースの R2 Data Catalog(Iceberg互換)はR2をLakehouseのバックエンドとしても使えるように拡張しました。
弱みは AWS S3との100%互換ではない ことです。Object Lambda、S3 Select、S3 Inventoryのような高度な機能は欠けています。PUT/GET/LIST + Multipart + Presigned URLしか使わない90%のケースでは差はほぼありません。
7. Backblaze B2 / Wasabi / Tigris — S3互換 + コスパ
S3互換のバリュー層はR2以前から存在し、それぞれ異なるポジションを持っています。
Backblaze B2(backblaze.com/b2)は2015年リリースのもっとも古いS3代替で、GB単価0.006 USDとR2よりさらに安く、Cloudflareとの「Bandwidth Alliance」 のおかげでB2からCloudflare CDNへ抜けるトラフィックは無料になります。2026年5月時点ではメディアバックアップとアーカイブ市場で最大シェアです。
# B2 CLI
b2 authorize-account $KEY_ID $APP_KEY
b2 upload-file my-bucket video.mp4 videos/2026/may.mp4
b2 download-file-by-name my-bucket videos/2026/may.mp4 ./local.mp4
Wasabi(wasabi.com)は2017年創業のS3互換ストレージで、GB単価0.0068 USDかつエグレス無料が核です。AWS S3経験者が作っているので互換性が非常に高く、料金モデルは「Hot Storage」一本で単純です。弱点は 30日の最小保管期間 があり、頻繁に消すトランザクションデータには非効率な点です。
Tigris(tigrisdata.com)はFly.ioが後援する2024年リリースの新顔S3互換ストレージで、グローバル自動レプリケーション が差別化です。オブジェクトをPUTすると最寄りのリージョンから順に全世界へ自動的に複製されていくため、初回GETがどこから来ても速くなります。Fly.io上で動くアプリにとってはルーティング費用が0です。
// TigrisもS3 SDKそのまま
const tigris = new S3Client({
region: 'auto',
endpoint: 'https://fly.storage.tigris.dev',
credentials: { accessKeyId: KEY, secretAccessKey: SECRET },
})
価格比較(2026年5月、標準ホット階層):
| 製品 | ストレージ(GB/月) | エグレス(GB) | 特徴 |
|---|---|---|---|
| AWS S3 Standard | 0.023 USD | 0.09 USD | 標準 |
| Cloudflare R2 | 0.015 USD | 0 USD | Workers/CDN統合 |
| Backblaze B2 | 0.006 USD | 0 USD(Cloudflare経由) | 最安 |
| Wasabi | 0.0068 USD | 0 USD | 30日最小保管 |
| Tigris | 0.02 USD | 0 USD | グローバル自動複製 |
8. Vercel Blob / Bunny Storage — クラウドビルトイン
プラットフォーム自身が提供するビルトインストレージも急速に伸びています。
Vercel Blob(vercel.com/storage/blob)は2024年にGAしたVercelのS3互換ストレージで、内部的にはCloudflare R2の上に乗ったマネージドレイヤーです。核は Vercelファンクションから一行のSDKでアップロードできる こと、そして自動でVercel Edge CDNにキャッシュされる点です。
// app/api/upload/route.ts
import { put } from '@vercel/blob'
export async function POST(req: Request) {
const file = (await req.formData()).get('file') as File
const blob = await put(`uploads/${file.name}`, file, {
access: 'public',
addRandomSuffix: true,
})
return Response.json(blob)
}
大きなファイル向けにはクライアント直接アップロードのパターンもあります。@vercel/blob/clientのupload(...)はサーバーにはトークン発行だけを問い合わせ、本体はVercel Blobへ直接PUTします。Vercel Functionsの4.5MBボディ制限を回避する定番手法です。
Bunny Storage(bunny.net/storage)はスロベニア発のBunny.net CDNが提供するオブジェクトストレージで、Bunny CDNとの統合 が強みです。GB単価0.01 USDでグローバル11リージョン複製、Pull Zoneと自動連携してCDNキャッシュまで一気に組めます。WordPressやDrupalのようなレガシーCMSのメディアバックエンドとして急速に定着しました。
# Bunny Storage API
curl -X PUT https://storage.bunnycdn.com/$STORAGE_ZONE/$PATH/file.jpg \
-H "AccessKey: $ACCESS_KEY" \
--data-binary @file.jpg
プラットフォームビルトインの共通の利点は インフラ結合度 です。Vercel BlobはVercel Edgeから最速、Bunny StorageはBunny CDNから最速です。共通の弱みは ロックイン で、プラットフォームを離れた瞬間に互換SDKが消えます。
9. MinIO — セルフホストS3互換OSS
企業が自社データセンターにオブジェクトストレージを置きたいときの事実上の標準が MinIO(min.io)です。2015年公開のGo製OSSで、GitHubスター48k超です。
強みは もっとも完全なS3 API互換実装 と 単一バイナリでのインストール です。
# 単一ノード(開発用)
docker run -p 9000:9000 -p 9001:9001 \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=secret123" \
-v /data:/data \
quay.io/minio/minio server /data --console-address ":9001"
# 分散クラスター(4ノード×4ディスク = 16イレイジャー)
minio server http://node{1...4}/data{1...4} \
--console-address ":9001"
MinIOは Erasure Coding によりノードやディスクの一部が落ちてもデータを失いません。16ディスクのうち8本まで同時に失敗しても復旧できる構成が既定で、社内バックアップ、機械学習データレイク、CIアーティファクトの保管庫といった用途に強いです。
2024年からMinIOは AIStor というAI/ML特化ブランドとして再ポジショニングしており、PyTorch、TensorFlow、NVIDIA NIMとの直接統合を打ち出しています。同じS3互換APIの上でペタバイト級の学習データを扱う市場を狙っています。
ライセンス上の論点はあります。2025年4月、MinIOは一部機能をAGPL v3から MinIO Commercial License(独自ライセンス)に移しました。自社SaaSに組み込むには商用ライセンスが必要なケースがあり、OSS純粋派は代替を探し始めています。それが次章のSeaweedFSとGarageです。
10. SeaweedFS / Garage (Deuxfleurs) — その他のOSS
SeaweedFS(github.com/seaweedfs/seaweedfs)は2014年初公開のGo製分散オブジェクトストレージで、「Haystackスタイル + S3互換」が特徴です。FacebookがHaystack論文(2010)で示した「数十億の小さなファイルを効率的に保存する」設計に着想を得ています。
# SeaweedFS master + volume + S3ゲートウェイ
weed master -mdir /data/master &
weed volume -dir /data/volumes -port 8080 -mserver localhost:9333 &
weed s3 -port 8333 -filer localhost:8888 &
特徴:
- 小さなファイルに強い(メタデータオーバーヘッドが最小)
- Filer経由でPOSIX-likeなAPIも提供
- S3、WebDAV、FUSE、HDFSゲートウェイを同時に公開
- AGPL v3(サーバー)、Apache 2.0(ライブラリ)
Garage(garagehq.deuxfleurs.fr)はフランスのDeuxfleursコレクティブが2020年に始めた新顔のS3互換OSSで、「低消費電力・低リソース環境」が特徴です。Raspberry PiのようなARMボードや家庭用のインターネット回線で分散クラスターを組めるように設計されています。
Garageの差別化点:
- 100% Rust実装で、メモリ消費が非常に少ない
- マルチリージョン・マルチデータセンターをネイティブにサポート
- AGPL v3
- 3〜10ノード程度の小規模クラスターに最適化
# Garageクラスター(各ノードで)
garage server &
# ノードID交換後
garage layout assign -z eu-west -c 1T <node-id>
garage layout apply --version 1
MinIOがエンタープライズやペタバイトを狙うのに対し、Garageは コミュニティ運営・フリーソフトウェア・小規模インフラ を狙います。Fediverse(Mastodon)やNextCloudの運営者がよく選びます。
11. Pinata — IPFSホスティング
ここからは 分散ストレージ(Decentralized Storage) のカテゴリです。Pinata(pinata.cloud)は2018年に米国で創業されたIPFSピンサービスで、NFTやWeb3市場では事実上の標準です。
IPFS(InterPlanetary File System)はコンテンツのハッシュ(CID)でファイルを識別するP2Pプロトコルです。同じファイルはどこに保存されていようが同じCIDを持ち、一度ピンすればP2Pネットワーク上のどのピアからでも取得できます。難点は 誰かがピンを維持する必要がある ことで、PinataがそれをSaaSとして売っています。
import PinataSDK from 'pinata'
const pinata = new PinataSDK({
pinataJwt: process.env.PINATA_JWT!,
pinataGateway: 'https://gateway.pinata.cloud',
})
// ファイルアップロード + IPFSピン
const result = await pinata.upload.file(file)
console.log(result.IpfsHash) // "QmXxx..."
// ユーザー向けゲートウェイURL
const url = `https://gateway.pinata.cloud/ipfs/${result.IpfsHash}`
2024年リリースの Pinata Files API は、公開IPFS DHTではなくPinata専用のプライベートネットワークに保存する新モードを追加しました。通常のオブジェクトストレージと同じ速度で扱え、必要なときだけ公開IPFSにエクスポートできます。これによりPinataは「Web3専用SaaS」から「IPFSオプション付きの汎用オブジェクトストレージ」に拡張しつつあります。
NFTのワークフローでPinataがよく使われる典型的なパターンは OpenSea互換のメタデータをIPFSにピン し、そのCIDをスマートコントラクトに刻むというものです。これによりトークンのメタデータに永続性と検閲耐性が担保されます。
12. Filebase / Storj DCS / Arweave — 分散 + 永久保存
分散ストレージのカテゴリにはPinata以外にもバックエンドが揃っています。
Filebase(filebase.com)は2019年創業の米国企業で、S3互換API でIPFS、Sia、Skynet、Filecoinといった分散ネットワークに保存します。利用者はS3 SDKだけ知っていれば、裏でどの分散ネットワークを使うかはバケット設定で決まります。
# FilebaseはS3 SDKをそのまま使える
aws s3 cp ./photo.jpg s3://my-bucket/photo.jpg \
--endpoint-url https://s3.filebase.com \
--profile filebase
GB単価約0.0059 USDで、各オブジェクトに自動でIPFS CIDが付与されます。
Storj DCS(storj.io)は2018年にメインネットを立ち上げた分散ストレージで、各オブジェクトを80個のリードソロモン消失訂正ピースに分割し、世界中の1.5万を超えるノードに分散保存します。任意の39ピースで復元でき、クライアント側暗号化により単一のノードからデータを読み出すことはできません。
uplink cp video.mp4 sj://my-bucket/video.mp4
料金はストレージGB単価0.004 USD、エグレス0.007 USDでR2と同等です。AWSやAzureを信用したくない政府・研究機関・メディアでシェアが高めです。
Arweave(arweave.org)は他のすべてと別のカテゴリです。一度料金を払えば200年保管を保証する 永久保存ブロックチェーンです。一般的なオブジェクトストレージの月額課金モデルではなく、アップロード時点で一度だけ支払い、以後は永遠に保管されます。
# Bundlr/Irysゲートウェイ
npx @irys/sdk fund 100000 -t arweave -w wallet.json
npx @irys/sdk upload file.jpg -t arweave -w wallet.json
# → Arweave Transaction IDが返る
費用はGB単価約5〜10 USDと絶対値では高めですが、永遠 という保証が付きます。法的証拠、ジャーナリズムのバックアップ、科学データ、ゲームアセットのように「二度と消えてはいけない」コンテンツに使われます。2025年以降はSolanaやEthereumのバックエンドもIrys/Bundlr経由で同じパターンをサポートしており、「ブロックチェーン永続性」市場が拡大中です。
13. tusプロトコル — 再開可能アップロード
tus.ioは2014年にTransloaditが始めた 再開可能アップロードプロトコル で、2026年現在IETF Internet-Draftが進行中、事実上の標準です。Uppy、UploadThing、Vimeo、Cloudflare R2、Vercel Blob、GitLab、ownCloudなどほぼすべての主要サービスがサポートしています。
中心アイデアは極端にシンプルで、HEADで現在のオフセットを尋ね、PATCHでその地点から続ける です。
# 1) アップロードを生成
POST /files HTTP/1.1
Upload-Length: 1073741824
Upload-Metadata: filename dmlkZW8ubXA0
Tus-Resumable: 1.0.0
→ 201 Created
Location: /files/abc123
# 2) ネットワーク切断後、現在のオフセットを確認
HEAD /files/abc123
→ 200 OK
Upload-Offset: 524288000
Upload-Length: 1073741824
# 3) その地点から再開
PATCH /files/abc123 HTTP/1.1
Upload-Offset: 524288000
Content-Type: application/offset+octet-stream
Tus-Resumable: 1.0.0
[バイナリチャンク]
→ 204 No Content
このシンプルな規約のおかげで、99%まで上がった1GBファイルがWi-Fi切断で落ちても、次にWi-Fiが入った瞬間にちょうど99%から続きを上げられます。モバイルや衛星のように切断が頻繁な環境では本質的です。
サーバー側の実装はいくつかあります。
# tusd(公式Go実装)
docker run -p 1080:1080 \
-v /data:/srv/tusd-data \
tusproject/tusd:latest \
-upload-dir=/srv/tusd-data
# Node用tusサーバー
npm i @tus/server @tus/file-store
import { Server } from '@tus/server'
import { FileStore } from '@tus/file-store'
const tus = new Server({
path: '/files',
datastore: new FileStore({ directory: './uploads' }),
})
// Next.jsのroute handlerにそのままマウント
クライアント側はtus-js-clientまたはUppyの@uppy/tusプラグインが定番です。どちらも自動リトライ、指数バックオフ、localStorageベースのフィンガープリント(同じファイルを同じセッションとして認識)を提供します。
2025年にtus 2.0の草案が公開され、HTTP/3 + 0-RTT、並列チャンク、署名付きメタデータ などが追加されました。正式発表は2026年後半を目標にしています。
14. ClamAV / Sublime Security — ウイルススキャン
アップロードされたファイルをそのままダウンロードリンクで公開すると、ユーザーから「このサイトで落としたPDFがランサムウェアだった」という事故報告が届きます。2026年では アップロード直後のマルウェアスキャンが事実上必須 です。
ClamAV(clamav.net)は1996年から続くオープンソースのアンチウイルスエンジンで、シグネチャベースで既知のマルウェアを検出します。
# ClamAVデーモンをDockerで起動
docker run -d --name clamav \
-p 3310:3310 \
-v clam_db:/var/lib/clamav \
clamav/clamav:stable
# ファイルをスキャン
clamdscan --multiscan /uploads/file.pdf
# /uploads/file.pdf: OK
# あるいは: /uploads/file.pdf: Eicar-Test-Signature FOUND
// NodeからClamAVのTCPデーモンに接続
import { NodeClam } from 'clamscan'
const clam = await new NodeClam().init({
clamdscan: { host: 'clamav', port: 3310 },
})
const { isInfected, viruses } = await clam.scanFile('/uploads/file.pdf')
if (isInfected) {
await deleteFromStorage(key)
throw new Error(`Malware detected: ${viruses.join(', ')}`)
}
ClamAVは高速ですが シグネチャベースの限界 があり、新種やゼロデイは見逃します。そのためマネージドのソリューションと併用するチームが多いです。
Sublime Security(sublimesecurity.com)は2020年に米国で創業されたコンテンツセキュリティSaaSで、もともとはメール用でしたが、2024年のシリーズB調達後にアップロードパイプライン市場へ拡張しました。メール本文、アップロードされた文書、HTMLペイロードに対してヒューリスティック + LLMベースの検査を提供します。
// 概念的なSublime Detection API
const res = await fetch('https://api.sublime.security/v1/scan', {
method: 'POST',
headers: { Authorization: `Bearer ${SUBLIME_KEY}` },
body: file,
})
const verdict = await res.json()
// { score: 0.92, label: 'phishing', signals: ['embedded-macro', 'suspicious-url'] }
その他の選択肢:
- VirusTotal(
virustotal.com) — Google運営、70超のエンジンで並列検査、無料APIと有料Premium - Cloudmersive Virus Scan API — マネージドのREST API
- MetaDefender Cloud(OPSWAT) — 30超のエンジン同時検査、マルチスキャンの代表
- AWS GuardDuty Malware Protection for S3 — 2024年GA、S3にPUTされたオブジェクトを自動スキャン
推奨されるアップロードパイプラインの形は次のとおりです。
- クライアント → Presigned URL/tus経由でS3/R2の 隔離バケット にPUT
- イベント(S3 ObjectCreated、R2 Queue、Vercel Blob webhook)が発火
- ClamAV/GuardDuty/Sublimeがスキャン
- クリーンなら 公開バケット へ移動、マルウェアならquarantineへ隔離
このパターンがZIP、TAR、WebAssemblyモジュールのような潜在的に危険なコンテンツを安全に扱う道です。
15. 日本・韓国 — Toss、カカオ、メルカリ
Toss(トス) — 2024年に韓国のフィンテック市場でトップに立ったTossは、KYC文書・身分証・契約書のような機微なファイルを毎日数百万件受け取ります。Toss Tech Blogで公開されている内容を総合すると、次のパターンが見えます。
- クライアント側: 自社製React Nativeモジュールで撮影直後にEXIF除去とリサイズ
- 転送層: HTTPS PUT + 独自のチャンクプロトコル(tusに類似)
- 一次保存: AWS S3の隔離バケット(
uploads-quarantine) - スキャン: ClamAV + 自社LLMヒューリスティック(写真の中の身分証が有効なKYC文書か自動判定)
- 二次保存: AWS S3 KMS暗号化バケット、アクセスはマイクロサービスごとのIAM Role
- CDN: CloudFront + Signed URL
Tossが強調するポイントは、「アップロード直後30秒以内にすべてのスキャンが完了し、ユーザーが次のステップに進めること」というSLAで、非同期キューではなく同期 + 高速ポーリングのモデルを採っています。
カカオ(Kakao) — KakaoTalkの動画メッセージ、KakaoStory、KakaoTVは日次でペタバイト級のメディアトラフィックを処理します。Kakaoテックブログによれば、自社オブジェクトストレージ KakaoCloud Object Storage(2022年公開、社内SeaweedFS派生 + 独自メタデータレイヤー)とAWS S3、GCSをマルチクラウドで運用します。韓国国内トラフィックはKakaoCloud、グローバルはS3 + CloudFrontに振り分けてエグレスコストを最適化します。
メルカリ(Mercari) — 日本最大のC2Cマーケットプレイスで、毎日数千万枚の写真を受け取ります。メルカリのエンジニアリングブログによれば、ベースはGCPのCloud Storage + Cloud CDNで、画像リサイズは自作のimageflux互換レイヤーで処理します。2024年以降は AIによる自動カテゴリ分類 がアップロード直後に走り、同じパイプラインで不適切コンテンツ(NSFW、偽造品の疑い)を自動で弾きます。
SmartHR — 日本の大手HR SaaSで、労働契約書や給与明細などの法的文書を扱います。AWS S3 + KMS暗号化 + Object Lock(WORM)で7年保管義務を満たし、ユーザーがダウンロードする瞬間に一度限りの署名付きURLを発行します。韓国のTossと日本のSmartHRが似たような規制環境にいることから、ファイルインフラのパターンも非常によく似ています。
3社に共通するのは(1)コアにS3互換APIを置く、(2)クライアントは自社製RN/Androidモジュールでチャンク・リトライ・EXIFを処理する、(3)サーバー側のスキャンが同期で完了してから次のステップに進む、という3点です。
16. 誰が何を選ぶべきか
規模とシナリオ別の推奨マトリクスです。
| シナリオ | 第一候補 | 第二候補 | 理由 |
|---|---|---|---|
| Next.js個人サイドプロジェクト | UploadThing | Vercel Blob | ゼロコンフィグ、無料枠 |
| Next.jsスタートアップ、自社認証 | Uppy + R2 Presigned URL | Uppy + S3 | エグレス削減、ロックイン回避 |
| 韓国フィンテックスタートアップ | Uppy + AWS S3 KMS + ClamAV | Uppy + KakaoCloud | 規制要件、KMS統合 |
| メディア重視(画像・動画変換) | Cloudinary または ImageKit | Filestack | URL変換、AI自動タグ付け |
| グローバルSaaS、エグレス大 | Cloudflare R2 + Uppy tus | Backblaze B2 + CDN | エグレス0 |
| ペタバイト級自社データセンター | MinIO | SeaweedFS | S3互換、Erasure Coding |
| 家庭用・小規模OSSクラスター | Garage | SeaweedFS | 低電力、マルチリージョン |
| NFT・Web3メタデータ | Pinata IPFS | Filebase | OpenSea互換、永続性 |
| 法務・科学・ジャーナリズム永久保存 | Arweave(Irys経由) | Storj DCS | 一度払い、検閲耐性 |
| エンタープライズ + マルチクラウド抽象化 | MinIO + S3 + R2 fan-out | Tigris(グローバル複製) | ベンダーロックイン回避 |
| 大きなファイル(>1GB) | tus + Uppy + R2 | tus + tusd + S3 multipart | 再開可能が本質 |
| 厳格なウイルスゲート要件 | ClamAV + S3隔離パターン | Sublime Security + GuardDuty | 多層防御 |
原則的な推奨:
- クライアントはUppyを — 1人プロトタイプでなければほぼ常にUppyを使ってください。UI、進捗、リトライ、tus、チャンキング、外部ソースが無料で付いてきます。
- ストレージはS3互換を — ロックインを避けるなら最初からS3 APIに準拠したバックエンドを選びましょう。R2、B2、Wasabi、MinIO、Tigrisはいずれも同じSDKです。
- エグレスが大きければR2かB2 — メディア配信が本業なら、エグレス0 USDの料金体系が決定打になります。
- 大きなファイルは必ずtus — 1GBを超えた瞬間からtusなしのアップロードは非効率です。
- 機微なファイルは隔離 → スキャン → 公開の3段階 — 受け取ったファイルを即座に公開URLに出さないでください。隔離バケットで受け、スキャンを通してから公開バケットへ昇格させましょう。
- EXIF・メタデータはクライアントで除去 — 写真のGPSや機種情報はサーバーに届く前に消すべきです。
piexifjsやexif-stripper-jsで十分です。 - 分散ストレージは永続性が本当に必要なときだけ — IPFSやArweaveは優れたツールですが、通常のSaaSにはオーバーキルです。「このデータは100年後にも存在するべきか?」がYesのときだけ使いましょう。
ファイルアップロードは決済と並んでユーザーに直接見える流れです。1GBの動画が99%で落ちたユーザーはそのサービスを信用しなくなり、一度マルウェアを通してしまったサービスは評判を取り戻すのが難しいです。2026年のツール群はこの2つの問題を一行のAPIで縮めてくれるので、遠慮なく活用してください。
参考 / References
- Uppy by Transloadit: https://uppy.io
- Uppy GitHub: https://github.com/transloadit/uppy
- UploadThing: https://uploadthing.com
- UploadThing Docs: https://docs.uploadthing.com
- Filestack: https://www.filestack.com
- Cloudinary: https://cloudinary.com
- ImageKit: https://imagekit.io
- AWS S3 Presigned URLs: https://docs.aws.amazon.com/AmazonS3/latest/userguide/PresignedUrlUploadObject.html
- Cloudflare R2: https://developers.cloudflare.com/r2/
- Backblaze B2: https://www.backblaze.com/cloud-storage
- Wasabi: https://wasabi.com
- Tigris: https://www.tigrisdata.com
- Vercel Blob: https://vercel.com/docs/storage/vercel-blob
- Bunny Storage: https://bunny.net/storage/
- MinIO: https://min.io
- SeaweedFS: https://github.com/seaweedfs/seaweedfs
- Garage (Deuxfleurs): https://garagehq.deuxfleurs.fr
- Pinata: https://www.pinata.cloud
- Filebase: https://filebase.com
- Storj DCS: https://www.storj.io
- Arweave: https://www.arweave.org
- tus protocol: https://tus.io
- tus IETF Internet-Draft: https://datatracker.ietf.org/doc/draft-tus-httpbis-resumable-uploads-protocol/
- ClamAV: https://www.clamav.net
- Sublime Security: https://sublimesecurity.com
- VirusTotal: https://www.virustotal.com
- AWS GuardDuty Malware Protection for S3: https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection-s3.html
- Standard Webhooks: https://www.standardwebhooks.com(関連するSvixエコシステム)
- Toss Tech Blog: https://toss.tech
- Kakao Tech: https://tech.kakao.com
- Mercari Engineering: https://engineering.mercari.com
- SmartHR Tech Blog: https://tech.smarthr.jp