git clone https://github.com/Monadical-SAS/zervice.backblaze.git
cd zervice.backblaze/
pipenv install
yarn install
b2 authorize-account # use master key for this, not app key
# edit cors_rules.json contents
b2 update-bucket bucket-name --corsRules "$(cat cors_rules.json)"
yarn run start
open http://localhost:8085
- Set up a BackBlaze account and create a new B2 bucket (public)
- Create a new Backblaze Application Key to authenticate your backend
- Update the bucket's CORS rules to allow requests from your website
b2 authorize-account # use master key for this, not app key
b2 update-bucket bucket-name --corsRules "$(cat cors_rules.json)"
- Start the webserver
yarn install
yarn run start
open http://localhost:8085
- user visits
index.html
, selects a file, andonSelectFile
is triggered - frontend requests a one-time B2 upload url via backend
frontend ->
localhost:8085/b2/getUploadUrl
-> server ->backblaze.com/api/getUploadUrl
- frontend calculates the file's sha1hash
- frontend prepares upload headers for B2 for:
- filename
- content type
- sha1 hash verification
- cache control behavior
- optional extra metadata
- frontend uploads file from browser to server-provided B2 uploadUrl with the prepared headers
Egress from BackBlaze is free if it goes through CloudFlare's network. To take advantage of this, you just need to create a domain that's a proxied CNAME to your B2 bucket's friendly URL.
- Create a CNAME record to point to your BackBlaze b2 bucket host
b2.example.com CNAME -> f000.backblazeb2.com (Proxied)
- Create a Page Rule on that domain to enable caching
b2.example.com/file/bukcet-name/*
:Always cache
# or do the same thing via the API
curl -X PUT "https://api.cloudflare.com/client/v4/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records/372e67954025e0ba6aaa6d586b9e0b59" \
-H "X-Auth-Email: user@example.com" \
-H "X-Auth-Key: c2547eb745079dac9320b638f5e225cf483cc5cfdda41" \
-H "Content-Type: application/json" \
--data '{"type":"CNAME","name":"b2.example.com","content":"f002.backblazeb2.com","ttl":{},"proxied":true}'
B2 does not allowget_upload_url
and delete_file_version
to be called directly from browsers due to b2's CORS restrictions.
You must ask a node backend to make the request for you.
The headers used for in-browser uploads *must be explicitly marked allowed in your b2 bucket's corsRules
. If not set properly, uploads will return CORS and 400 errors. The rules can be set up using the b2 CLI.
b2 update-bucket --corsRules rules.json bucket-name
Browser's hash needs to match backblaze's hash result exactly or the b2 upload will fail with a 400 error.
Footgun: use 'do_not_verify'
as the hash to disable hash verification.
Always explicity pick the expected content type (e.g. 'audio/mpeg', 'application/octet-stream', etc.) to prevent accidentally reflecting user-uploads as public runnable JS/HTML/viruses/etc types to others.
Footgun: use 'b2/x-auto'
as the ctype to have b2 autodetect it.
Your B2 filenames will be served via public URLs on your domain.
Beware of using user-provided filenames! Do you really want someont to upload yourfiles.com/passwod_reset.html
?
Tip: you can use the hash as the name instead
The Content-Length header will be automatically set to the correct length by the browser making the upload request.
While uploading can be done without axios
to make the requests from the browser -> B2, it's more difficult to get the CORS headers right with fetch()
or XMLHttpRequst
.