runlot
데이터스토리지

put · get · list

올리고, 내려받고, 훑습니다.

올리기

app.post("/upload", async (c) => {
  const form = await c.req.formData();
  const file = form.get("file") as File;
  const obj = await c.env.storage.put(`covers/${file.name}`, file, {
    contentType: file.type,
  });
  return Response.json({ key: obj.key, size: obj.size, etag: obj.etag });
});

body 로는 Response/Request 에 넣을 수 있는 것이면 무엇이든 됩니다 — File, Blob, ArrayBuffer, ReadableStream, 문자열.

contentType 을 주지 않으면 기본값이 붙습니다. 브라우저가 그대로 열어야 하는 파일이라면 지정하세요.

내려받기

const obj = await env.storage.get(key);
if (!obj) return new Response("없어요", { status: 404 });

return new Response(obj.body, {
  headers: {
    "content-type": obj.contentType,
    "content-length": String(obj.size),
    etag: obj.etag,
  },
});

body 는 스트림입니다. 통째로 메모리에 올리지 않고 그대로 흘려보낼 수 있습니다.

메타데이터만 필요하면 head 를 쓰세요.

const meta = await env.storage.head(key);
if (meta && meta.etag === request.headers.get("if-none-match")) {
  return new Response(null, { status: 304 });
}

지우기

await env.storage.delete(key);

훑기

let cursor = "";
do {
  const page = await env.storage.list({ prefix: "covers/", cursor, limit: 100 });
  for (const obj of page.objects) {
    console.log(obj.key, obj.size);
  }
  cursor = page.cursor;
} while (cursor !== "");

cursor 가 빈 문자열이면 마지막 쪽입니다. limit 은 기본 100, 최대 1000 입니다.

prefix 는 디렉토리가 아니라 문자열 접두입니다 — covers/ 로 시작하는 모든 키가 나옵니다.

큰 파일은 브라우저가 직접

워커를 거쳐 업로드하면 그 요청이 워커의 시간과 메모리를 씁니다. 큰 파일은 서명 URL 로 브라우저가 직접 올리게 하세요.

이 페이지에서