Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
RemixとCloudflare Stack におけるFile Upload
Search
Ossamoon
September 25, 2024
Programming
450
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RemixとCloudflare Stack におけるFile Upload
Ossamoon
September 25, 2024
More Decks by Ossamoon
See All by Ossamoon
楽譜フォント(SMuFL)をCloudflareで配信する
ossamoon
0
170
SSRアプリケーションにおけるPKCE付き認可コードフロー
ossamoon
0
75
Other Decks in Programming
See All in Programming
Agents on Rails - Rails at Scale 2026
irinanazarova
0
200
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
0
1.8k
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
16
14k
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
660
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
160
AI活用は、個人から組織へ|マルチプレイヤーエージェントハーネス「QM」の社内活用事例 / AI use is moving from individuals to orgs
rkaga
1
170
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
260
FreeBSDでZabbixを動かす
kenkino
0
320
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
440
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
7
2.2k
iOSDC2026登壇資料.pdf
riofujimon
0
180
wkhtmltopdfの次どうするか問題2026
willnet
2
1.6k
Featured
See All Featured
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
500
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
530
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
550
The SEO Collaboration Effect
kristinabergwall1
1
570
Paper Plane
katiecoart
PRO
4
53k
Designing Experiences People Love
moore
143
24k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
5
730
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
360
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
From π to Pie charts
rasagy
1
380
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
730
Transcript
RemixとCloudflare Stack におけるFile Upload Remix Tokyo Meetup, 2024.09.25
自己紹介 - 齋藤 修(Ossamoon) - Webフロントエンジニア - Reactばかり触っている - フリーランス
- 趣味:音楽 - クラシック音楽が好き
Remixを使ったプロダクトを個人開発中 - クラシック音楽の音源をクラウドにアップロード - 楽譜を表示しながらストリーミング再生 最初の壁として立ちはだかったのが、File Upload
File Uploadに求めること - 認証・認可 - ユーザーを認証したい - アップロード上限を超えていないかをチェックしたい - データベースの更新
- アップロードした音源に関する情報をデータベースに保存したい - アップロードに失敗した場合はデータベースの更新も失敗して欲しい( Atomicity: 原子性) - Cloudflareの制約を満たす - 特にCloudflare Workersは実行時間やメモリの制約が厳しいため、考慮する必要がある
RemixにおけるFile Upload
RemixのFile Uploadに関するAPI - unstable_parseMultipartFormData - unstable_createMemoryUploadHandler - unstable_createFileUploadHandler - Node.jsでのみ動作
- unstable_composeUploadHandlers - APIリファレンスにも載っていない内部的な API すべてmultipart/form-dataを使う想定のAPI 今回は この2つを利用 ← ←
multipart/form-dataとは - HTTPに定義されている仕様 - formに入力したテキストと ファイルのバイナリを 同時に送信できる POST /upload HTTP/1.1
Host: example.com Content-Type: multipart/form-data; boundary=----- Content-Length: 1024 ----- Content-Disposition: form-data; name="field1" value1 ----- Content-Disposition: form-data; name="field2" value2 ----- Content-Disposition: form-data; name="file"; filename="example.jpg" Content-Type: image/jpeg (...ファイルのバイナリデータ...) -----
APIの使い方(action) const uploadHandler = unstable_createMemoryUploadHandler({ maxPartSize: 5 * 1024 *
1024, // これを超えるサイズのファイルは扱えない }); const formData = await unstable_parseMultipartFormData(request, uploadHandler); const title = formData.get("title") as string; const audioFile = formData.get("audiofile") as File; 1. unstable_createMemoryUploadHandler で uploadHandler を作成 2. unstable_parseMultipartFormData で formDataを作成 3. formDataから必要なデータを取得
export async function action({ request, context }: ActionFunctionArgs) { //
認証 const user = await authenticator.isAuthenticated(request); // FormDataを取得 const uploadHandler = unstable_createMemoryUploadHandler({ maxPartSize: 5 * 1024 * 1024, // 5MB }); const formData = await unstable_parseMultipartFormData( request, uploadHandler ); const title = String(formData.get("title")); const audioFile = formData.get("audiofile") as File; // R2にファイルをアップロード const { R2 } = context.cloudflare.env; const object_key = crypto.randomUUID(); const upload_info = await R2.put(object_key, await audioFile.arrayBuffer(), { httpMetadata: { contentType: audioFile.type, }, }); // TrackをDBに追加 const track = await db.track.create(object_key, title, user.id); redirect("tracks"); } 認証とDB更新 も含めた コードの全体像
APIの使い方(component) 1. <Form>のencTypeにmultipart/form-dataを指定 2. あとは普通のformと同様に書く <Form method="post" encType="multipart/form-data"> <label htmlFor="title">タイトル</label>
<input id="title" type="text" name="title" /> <label htmlFor="audiofile">音源ファイル</label> <input id="audiofile" accept="audio/*" type="file" name="audiofile" /> <button type="submit">送信</button> </Form>
multipart/form-dataのメリット・デメリット 👍 実装がシンプル 👍 認証・認可をaction内で処理できる 👍 DB更新も同じaction内で記述することができ る 👎 Workerの実行時間・使用メモリがファイルサ
イズに大きく依存する 👎 Multipart uploadやprogressの表示といった ユーザー体験の最適化が実現しにくい FileUploadのもう一つの実装方法である 署名付きURLも検討したい
署名付きURL
署名付きURLとは - 特定の操作(今回の場合はファイルのアップロード)を認可する署名を追加した URL - Cloudflare R2はS3互換であるため、署名付きURLを用いることができる - Workerで署名付きURLを発行し、クライアントからR2に直接ファイルをアップロード する
- 有効期限を適切に定める必要がある
署名付きURLの流れ 1. クライアントがWorkerに署名付き URLをリクエスト 2. Workerが認証 3. Workerがデータベースに新しいレ コードを作成 4.
Workerが署名付きURLを返す 5. クライアントが署名付きURLを用 いてR2にファイルをアップロード 6. クライアントがWorkerにアップ ロード完了を伝える 7. Workerがデータベースに追加し たレコードを更新 8. (定期実行) ファイルアップロード に失敗した分のデータを削除
署名付きURLのメリット・デメリット 👍 Workerの実行時間・使用メモリがファイル サイズに依存しない 👍 Multipart uploadやprogressの表示といった ユーザー体験の最適化が実現しやすい 👎 有効期限内の署名付き
URLを知れば誰でも アップロードができるので、認証・認可が完 全ではない 👎 Atomicityを保つために実装が複雑になって しまう
さらなるユーザー体験の向上へ - Multipart upload - ファイルをいくつかの partに分割してアップロードする - 並列化による最適化や、ネットワーク切断からの回復に貢献する -
大容量(だいたい100MB以上)のファイルアップロードによく使われる - Progressの表示 - ファイルの何%がアップロードできたかを表示したい - fetchのbodyにReadbleStreamを指定することで、経過を観察することができる - 上記機能はChromeでのみ利用可能 - 他のブラウザもサポートしたい場合、 XMLHttpRequestやaxiosを利用する必要がある これらはRemixの<Form>と組み合わせるのが難しいため、 署名付きURLと組み合わせて使う方がメリットを享受しやすい
まとめ - ファイルサイズが小さい場合は、multipart/form-dataを活用したい - なによりシンプルに書けるのがメリット - ファイルサイズが大きい場合は、署名付きURLを活用したい - ユーザー体験を追求したい場合は、署名付きURLを活用したい