Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- addEventListener('fetch', event => {
- event.respondWith(handleRequest(event.request))
- })
- /////////////////////////
- // Configure these
- /////////////////////////
- const key = 'KEY_ID';
- const appKey = 'APPLICATION_KEY';
- const bucketId = 'BUCKET_ID';
- const bucketName = 'BUCKET_NAME';
- const apiVer = 'b2api/v2';
- const downloadBase = `https://f002.backblazeb2.com/file/${bucketName}`;
- // 22 hours, it lasts for 24 hours but we expire early to just avoid any auth errors
- const detailsExpiration = 79200;
- const initialAuth = btoa(key + ':' + appKey);
- async function handleRequest(request) {
- // Only accept a POST
- if (request.method !== 'POST') {
- return new Response('{"error": "Bad request!"}');
- }
- // Parse the request to FormData
- const formData = await request.formData();
- // Get the File from the form. Key for the file is 'image' for me
- const image = formData.get('image');
- const details = await setup();
- if (!details) {
- return new Response('{"error": "Failed to upload!"}');
- }
- const fileName = await upload(details, image);
- if (!fileName) {
- return new Response('{"error": "Failed to upload!"}');
- }
- return new Response(`{"message": "Uploaded!", "file": "${fileName}", "b2Url": "${downloadBase}/${fileName}"}`);
- }
- // returns: { "apiUrl", "authToken", "bucketAuth", "uploadUrl" }
- async function setup() {
- // We will try and fetch the auth token and upload URL from KV.
- // They are valid for 24 hours so no need to request it every time
- // { "apiUrl", "authToken", "bucketAuth", "uploadUrl" }
- const storedDetails = await KV.get('details', 'json');
- if (storedDetails) {
- return storedDetails;
- }
- // If we are not authorized then let's do that!
- const details = {};
- const authRes = await fetch(`http://api.backblazeb2.com/${apiVer}/b2_authorize_account`, {
- headers: {
- Authorization: 'Basic ' + initialAuth
- }
- });
- const authJson = await authRes.json();
- if (!authRes.ok) {
- console.error('Failed to authenticate, got json:', authJson);
- return false;
- }
- // Grab the auth token from the responses
- details.apiUrl = authJson.apiUrl;
- details.authToken = authJson.authorizationToken;
- // Grab the upload URL
- const uploadRes = await fetch(`${authJson.apiUrl}/${apiVer}/b2_get_upload_url`, {
- method: 'POST',
- headers: {
- Authorization: authJson.authorizationToken
- },
- body: JSON.stringify({
- bucketId
- })
- });
- const uploadJson = await uploadRes.json();
- if (!uploadRes.ok) {
- console.error('Failed to get upload URL, got json:', uploadJson);
- return false;
- }
- details.bucketAuth = uploadJson.authorizationToken;
- details.uploadUrl = uploadJson.uploadUrl;
- // Write the details into KV so we can get them in future calls.
- // Note this can take up to 60 seconds to propagate globally.
- await KV.put('details', JSON.stringify(details), { expirationTtl: detailsExpiration });
- return details;
- }
- async function upload(details, file) {
- const extension = file.name.substring(file.name.lastIndexOf('.'));
- // I'm gonna use UUIDs for files here but you could use anything
- const uploadedFileName = crypto.randomUUID() + extension;
- const hash = await sha1(file);
- const res = await fetch(details.uploadUrl, {
- method: 'POST',
- headers: {
- 'Authorization': details.bucketAuth,
- 'X-Bz-File-Name': uploadedFileName,
- // We have the type and size of the image in File
- 'Content-Type': file.type,
- 'Content-Length': file.size,
- // SHA-1 of the file
- 'X-Bz-Content-Sha1': hash,
- },
- body: file.stream()
- });
- if (!res.ok) {
- const json = await res.json();
- console.error('Failed to upload, got json:', json);
- return false;
- }
- return uploadedFileName;
- }
- async function sha1(file) {
- const fileData = await file.arrayBuffer();
- const digest = await crypto.subtle.digest('SHA-1', fileData);
- const array = Array.from(new Uint8Array(digest));
- const sha1 = array.map(b => b.toString(16).padStart(2, '0')).join('')
- return sha1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement