I was able to stream an S3 object from disk to the browser using the following post request in Ruby:
post '/api/s3/download/?' do
filepath = "/tmp/test.txt"
send_file(filepath, :filename => File.basename(filepath))
end
And the following AngularJS in the javascript:
$http.post('/api/s3/download/')
.then(function(response) {
var blob = new Blob([response.data]);
var objectUrl = URL.createObjectURL(blob);
const anchor = angular.element('<a></a>');
anchor.attr('href', objectUrl);
anchor.attr('download', source);
anchor.css('display', 'none');
angular.element(document.body).append(anchor);
anchor[0].click();
}, function(error_msg) {
console.log(error_msg);
});
I've tried the following in Ruby to get an S3 object as a StringIO
where source
is the S3 object key:
s3 = Aws::S3::Resource.new
bucket = s3.bucket('my_bucket')
data = bucket.object(source).get
Then I tried returning data.body
as the response to the javascript but that didn't work.
How can I take a StringIO object and send it to the browser as an octet-stream without materializing the file to disk?
I got it working by using the following endpoint:
get '/api/s3/download' do
source = params[:source]
headers['Content-Type'] = 'application/octet-stream'
headers['Content-Disposition'] = "attachment; filename=#{source}"
stream do |out|
s3.client.get_object(bucket: 'my_bucket', key: source) do |chunk|
out << chunk
end
out.flush
end
end
And doing the following on the front end in Javascript opens a new tab in the browser that the download happens through:
$window.open('/api/s3/download?source=' + source), '_blank');
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.