← Cloudflare Workers KV / kv / examples
Хранение и получение статических файлов
Сохраняя статические ресурсы в Workers KV, вы можете получать их из любой точки мира с низкой задержкой и высокой пропускной способностью. Затем эти ресурсы можно отдавать напрямую или использовать для динамической генерации ответов. Это удобно, например, при раздаче таких файлов, как собственные скрипты или небольшие изображения, размер которых не превышает Лимиты KV, или при формировании динамических HTML ответов на основе статических ресурсов, таких как переводы.
Запись статических ресурсов в Workers KV с помощью Wrangler
Чтобы хранить статические ресурсы в Workers KV, можно использовать Wrangler CLI (обычно используется при разработке), Привязка Workers KV из приложения Workers, либо Workers KV REST API (обычно используется для доступа к Workers KV из внешнего приложения). Мы покажем, как использовать Wrangler CLI.
В этом сценарии мы сохраним пример HTML-файла в хранилище Workers KV.
Создайте новый файл index.html следующим содержимым:
Hello World!Затем можно использовать следующие команды Wrangler, чтобы создать пару KV для этого файла в рабочем и предварительном пространствах имён:
npx wrangler kv key put index.html --path index.html --namespace-id=<ENTER_NAMESPACE_ID_HERE>Это создаст пару KV, в которой ключом будет имя файла, а значением содержимое файла, в рабочем и предварительном пространствах имён, указанных в привязке вашего файла Wrangler.
Раздача статических файлов из KV через приложение Worker
В этом примере наше приложение Workers принимает в качестве пути HTTP-запроса любое имя ключа и возвращает значение, хранящееся в хранилище KV для этого ключа.
import mime from "mime";
interface Env {
assets: KVNamespace;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
// Return error if not a get request
if(request.method !== 'GET'){
return new Response('Method Not Allowed', {
status: 405,
})
}
// Get the key from the url & return error if key missing
const parsedUrl = new URL(request.url)
const key = parsedUrl.pathname.replace(/^\/+/, '') // Strip any preceding /'s
if(!key){
return new Response('Missing path in URL', {
status: 400
})
}
// Get the mimetype from the key path
const extension = key.split('.').pop();
let mimeType = mime.getType(extension) || "text/plain";
if (mimeType.startsWith("text") || mimeType === "application/javascript") {
mimeType += "; charset=utf-8";
}
// Get the value from the Workers KV store and return it if found
const value = await env.assets.get(key, 'arrayBuffer')
if(!value){
return new Response("Not found", {
status: 404
})
}
// Return the response from the Workers application with the value from the KV store
return new Response(value, {
status: 200,
headers: new Headers({
"Content-Type": mimeType
})
});
},
} satisfies ExportedHandler<Env>;{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "2025-03-03",
"observability": {
"enabled": true
},
"kv_namespaces": [
{
"binding": "assets",
"id": "<YOUR_BINDING_ID>"
}
]
}Этот код разбирает имя ключа пары ключ-значение для получения из HTTP-запроса. Затем он определяет подходящий MIME-тип ответа, чтобы сообщить браузеру, как его обрабатывать.
Чтобы получить значение из хранилища KV, этот код использует arrayBuffer для корректной работы с двоичными данными, такими как изображения, документы и видео- или аудиофайлы.
Возьмём пример пары «ключ-значение» с ключом index.html со значением, содержащим HTML код, в хранилище нашего пространства имён Workers KV, мы можем открыть наше приложение Workers
по адресу https://<YOUR-WORKER-HOSTNAME>/index.html чтобы просмотреть содержимое index.html файл.
Попробуйте использовать изображение или документ, и вы увидите, что этот Worker корректно отдаёт эти ресурсы из KV.
Формирование динамических ответов на основе пар «ключ-значение»
Помимо обслуживания статических ресурсов, мы можем также формировать динамические ответы в формате HTML или API на основе значений, хранящихся в нашем хранилище KV.
- Начните с создания этого файла в корневой папке проекта:
[
{
"language_code": "en",
"message": "Hello World!"
},
{
"language_code": "es",
"message": "¡Hola Mundo!"
},
{
"language_code": "fr",
"message": "Bonjour le monde!"
},
{
"language_code": "de",
"message": "Hallo Welt!"
},
{
"language_code": "zh",
"message": "你好,世界!"
},
{
"language_code": "ja",
"message": "こんにちは、世界!"
},
{
"language_code": "hi",
"message": "नमस्ते दुनिया!"
},
{
"language_code": "ar",
"message": "مرحبا بالعالم!"
}
]- Откройте терминал и введите следующую команду KV, чтобы создать запись KV для файла переводов:
npx wrangler kv key put hello-world.json --path hello-world.json --namespace-id=<ENTER_NAMESPACE_ID_HERE>- Обновите код своего Worker, добавив логику отдачи переведённого HTML-файла в зависимости от языка в заголовке запроса Accept-Language:
import mime from 'mime';
import parser from 'accept-language-parser'
interface Env {
assets: KVNamespace;
}
export default {
async fetch(request, env, ctx): Promise<Response> {
// Return error if not a get request
if(request.method !== 'GET'){
return new Response('Method Not Allowed', {
status: 405,
})
}
// Get the key from the url & return error if key missing
const parsedUrl = new URL(request.url)
const key = parsedUrl.pathname.replace(/^\/+/, '') // Strip any preceding /'s
if(!key){
return new Response('Missing path in URL', {
status: 400
})
}
// Add handler for translation path (with early return)
if(key === 'hello-world'){
// Retrieve the language header from the request and the translations from Workers KV
const languageHeader = request.headers.get('Accept-Language') || 'en' // Default to English
const translations : {
"language_code": string,
"message": string
}[] = await env.assets.get('hello-world.json', 'json') || [];
// Extract the requested language
const supportedLanguageCodes = translations.map(item => item.language_code)
const languageCode = parser.pick(supportedLanguageCodes, languageHeader, {
loose: true
})
// Get the message for the selected language
let selectedTranslation = translations.find(item => item.language_code === languageCode)
if(!selectedTranslation) selectedTranslation = translations.find(item => item.language_code === "en")
const helloWorldTranslated = selectedTranslation!['message'];
// Generate and return the translated html
const html = `<!DOCTYPE html>
<html>
<head>
<title>Hello World translation</title>
</head>
<body>
<h1>${helloWorldTranslated}</h1>
</body>
</html>
`
return new Response(html, {
status: 200,
headers: {
'Content-Type': 'text/html; charset=utf-8'
}
})
}
// Get the mimetype from the key path
const extension = key.split('.').pop();
let mimeType = mime.getType(extension) || "text/plain";
if (mimeType.startsWith("text") || mimeType === "application/javascript") {
mimeType += "; charset=utf-8";
}
// Get the value from the Workers KV store and return it if found
const value = await env.assets.get(key, 'arrayBuffer')
if(!value){
return new Response("Not found", {
status: 404
})
}
// Return the response from the Workers application with the value from the KV store
return new Response(value, {
status: 200,
headers: new Headers({
"Content-Type": mimeType
})
});
},
} satisfies ExportedHandler<Env>;{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "<ENTER_WORKER_NAME>",
"main": "src/index.ts",
"compatibility_date": "2025-03-03",
"observability": {
"enabled": true
},
"kv_namespaces": [
{
"binding": "assets",
"id": "<YOUR_BINDING_ID>"
}
]
}Этот новый код предоставляет отдельную конечную точку, /hello-world, который будет предоставлять переведённые ответы. При обращении по этому URL код нашего Worker сначала получает язык, запрошенный клиентом в Accept-Language заголовка запроса и переводов из нашего хранилища KV для hello-world.json ключ. Затем он получает переведённое сообщение и возвращает сформированный HTML.
При обращении к приложению Worker по адресу https://<YOUR-WORKER-HOSTNAME>/hello-world, мы видим, что наше приложение теперь возвращает корректно переведённое сообщение «Hello World».
В консоли разработчика браузера измените язык локали (в браузерах на основе Chromium выполните Show Sensors чтобы получить раскрывающийся список локалей). Вы увидите, что Worker теперь возвращает переведённое сообщение в зависимости от языка локали.