runlot
데이터스토리지

서명 URL

로그인하지 않은 사용자도 제한된 시간 동안 사용할 수 있는 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은 초 단위이며 최대 **3,600초(1시간)**입니다. 이 값을 초과하면 요청을 거절합니다.

브라우저가 직접 업로드하도록 구성하기

워커는 URL만 발급하고 파일 데이터는 워커를 거치지 않습니다.

// 워커
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을 만들 수 없습니다. 삭제 작업은 항상 워커에서 권한을 확인한 뒤 수행해야 합니다. 유출된 URL 하나가 파일 삭제 권한이 되는 것을 막기 위해서입니다.

스토리지 백엔드에 따른 제한

서명 URL은 오브젝트 스토리지 백엔드에서만 사용할 수 있습니다. 로컬 개발 환경처럼 디스크 백엔드를 사용하는 경우 501 오류(unsupported)를 반환합니다.

로컬에서 서명 URL을 사용하는 흐름을 테스트해야 한다면, 워커가 파일을 직접 반환하는 대체 경로를 둘 수 있습니다.

let url: string;
try {
  url = await env.storage.presign(key, { ttl: 600 });
} catch {
  url = `/files/${encodeURIComponent(key)}`; // 워커가 get으로 파일을 반환하는 경로
}

쿼터 초과 시 동작

쓰기용 서명 URL은 저장 용량이 가득 차면 발급되지 않습니다(507). 읽기용 URL은 계속 발급할 수 있습니다. 파일을 삭제해 용량을 확보할 수 있어야 하기 때문입니다.

이 페이지의 목차