Created
September 25, 2020 11:40
-
-
Save spencerldixon/0ac2b3ce10b5c843904de02120acb77c to your computer and use it in GitHub Desktop.
Azure Downloads and Zip Streaming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Service object azure_api.rb for interfacing with azure blob storage. Handles getting a list of files as well as | |
# getting files by top_level_directory/prefix and multiple prefixes. Also caches requests to ensure a fast response. | |
require 'azure/storage/blob' | |
CACHE_LENGTH = 3.hours | |
PREFIX_DELIMITER = ',' | |
class AzureApi | |
def self.get_files_for(directory, prefix=nil) | |
return self.list_blobs(directory) if prefix.nil? | |
prefixes = prefix.split(PREFIX_DELIMITER) | |
prefixes.flat_map do |prefix| | |
self.list_blobs(File.join(directory, prefix, '/')) | |
end | |
end | |
def self.list_blobs(prefix) | |
Rails.cache.fetch("get_files_for_#{AZURE_CONTAINER}_#{prefix}", expires_in: CACHE_LENGTH) do | |
AZURE_CLIENT.list_blobs(AZURE_CONTAINER, prefix: prefix) | |
end | |
end | |
def self.download(path) | |
Rails.cache.fetch("download_#{AZURE_CONTAINER}_#{path}", expires_in: CACHE_LENGTH) do | |
AZURE_CLIENT.get_blob(AZURE_CONTAINER, path) | |
end | |
end | |
end | |
########################## STREAMING ACTION FOR CONTROLLER ################## | |
def download_all_as_zip | |
# Generates a zip of all files given a Azure directory and a prefix | |
blobs = AzureApi.get_files_for(DIRECTORY, PREFIX) | |
send_file_headers!( | |
type: "application/zip", | |
disposition: "attachment", | |
filename: "download_#{Time.now.to_i}.zip" | |
) | |
response.headers["Last-Modified"] = Time.now.httpdate.to_s | |
response.headers["X-Accel-Buffering"] = "no" | |
writer = ZipTricks::BlockWrite.new do |chunk| | |
response.stream.write(chunk) | |
end | |
ZipTricks::Streamer.open(writer) do |zip| | |
blobs.each do |blob| | |
# Download each individual blob, takes the full path of the blob | |
_blob, content = AzureApi.download(blob.name) | |
zip.write_deflated_file(blob.name) do |file_writer| | |
# Add blob content to file writer to stream back to browser | |
file_writer << content | |
end | |
end | |
end | |
ensure | |
response.stream.close | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment