데이터스토리지
서명 URL
로그인 없이 잠깐 열리는 주소를 만듭니다. 업로드와 다운로드 둘 다 됩니다.
const url = await env.storage.presign("covers/hello.png");기본은 GET, 유효 기간 300 초 입니다.
await env.storage.presign(key, { method: "GET", ttl: 60 }); // 1 분짜리 다운로드
await env.storage.presign(key, { method: "PUT", ttl: 3600 }); // 1 시간짜리 업로드ttl 은 초 단위이고 상한은 3600 초(1 시간) 입니다. 넘기면 거절합니다.
브라우저가 직접 올리게 하기
워커는 주소만 발급하고, 파일 바이트는 워커를 지나지 않습니다.
// 워커
app.post("/upload-url", async (c) => {
const { name, type } = await c.req.json();
const key = `uploads/${crypto.randomUUID()}/${name}`;
const url = await c.env.storage.presign(key, { method: "PUT", ttl: 600 });
return Response.json({ key, url });
});// 브라우저
const { key, url } = await fetch("/upload-url", {
method: "POST",
body: JSON.stringify({ name: file.name, type: file.type }),
}).then((r) => r.json());
await fetch(url, { method: "PUT", body: file });키를 워커가 정하는 것이 중요합니다. 클라이언트가 준 이름을 그대로 키로 쓰면 남의 파일을 덮어쓸 수 있습니다.
GET 과 PUT 만 서명합니다
DELETE 는 서명하지 않습니다. 지우는 일은 언제나 워커를 지나야 합니다 — 새어 나간 주소 하나가 삭제 권한이 되어서는 안 되기 때문입니다.
백엔드에 따라
서명 URL 은 오브젝트 스토리지 백엔드에서만 됩니다. 로컬 개발 스택처럼 디스크 백엔드로 뜬 환경에서는
501 오류(unsupported)가 납니다.로컬에서 서명 URL 경로를 시험하셔야 하면, 워커가 직접 바이트를 내주는 대체 경로를 두시면 됩니다.
let url: string;
try {
url = await env.storage.presign(key, { ttl: 600 });
} catch {
url = `/files/${encodeURIComponent(key)}`; // 워커가 get 으로 내주는 경로
}쿼터를 넘으면
쓰기용 서명 URL 은 저장 용량이 가득 차면 발급되지 않습니다(507). 읽기용은 계속 발급됩니다 — 지워서 내려올 수 있어야 하기 때문입니다.