OpenURI::HTTPError in ArticlesController#download 403 Forbidden - S3 - Rails - ruby-on-rails

I'm simply trying to allow my app to download files that are stored on s3. This seems straight forward but I keep getting this error OpenURI::HTTPError in ArticlesController#download
403 Forbidden
Here is my controller:
def download
article = Article.find_by(id: params[:id])
data = File.read(open("https://s3.us-east-2.amazonaws.com/theranostics-bucket/uploads/DMS-OctoberSocialMedia.pdf"))
send_data data, filename: "file.pdf", type: "application/pdf", disposition: 'inline', stream: 'true', buffer_size: '4096'
end
It fails on the File.read line. What am I missing? I'm using Carrierwave to upload the files which is working just fine. It's only when I try to download I'm having issues.

Related

How to send json data without template?

I am learning rails and trying to modify some existing code. The code in question calls a separate server to render a PDF which is downloaded from the browser.
I would like to change it to just download a json file instead when in development.
Chrome appears to download the file but says "Failed - network error". When I inspect the download it seems to have no body in the response.
The server shows:
Completed 200 OK in 77ms (Views: 0.6ms | ActiveRecord: 16.7ms)
My controller code looks like this:
# if in development, just send the json to check
if Rails.env.development?
send_data json.to_json, :filename => 'account_statement.json', :type => 'application/json', :disposition => 'attachment'
else
begin
send_data generate_report(json.to_json), :filename => 'account_statement.pdf', :type => 'application/pdf', :disposition => 'attachment'
rescue => e
raise 'Report server is not available, Please try again later'
end
end
Printing the json.to_json to the console does also show a json string, so that seems fine.
How can I debug this further?

Streaming Large (7 GB) S3 gz file in Rails 3.x to the Browser

I'm trying to stream a large Amazon S3 file to the browser using the Rails send_data method, however because the file is so large, the server runs out of memory and cannot complete the request.
The code looks something like this:
def download
s3_obj.read
end
def download_file
send_data(file.download, :filename => filename, :type => 'application/gzip', :disposition => 'attachment')
end
Is there a way to stream the chunks of the file with send_data so that it's a single file in the browser? the way I understand it is that send_data has to load the entire file into memory, then send all of that at once.
You should use send_file instead of send_data as it allow you to set the buffer and more option.
More information here.
UPDATE
If you want to download from S3, you can do this:
def download
data = open("S3_OBJECT_URL")
send_file data.read, filename: filename, type: "application/gzip", disposition: 'attachment', stream: 'true', buffer_size: '4096'
end
or
redirect_to s3_object.file.url

Rails send_data streaming PDF as bytes, unless route accessed directly

I've got a simple Rails app that downloads a PDF from a (private) S3 bucket and serves it to the browser.
# app/controllers/file_controller.rb
class FileController < ApplicationController
def send_pdf
s3_file = Aws::S3::Resource.new(
region: "us-east-1",
access_key_id: S3_ACCESS_KEY_ID,
secret_access_key: S3_SECRET_ACCESS_KEY
).bucket('bucket-name').objects({prefix: "file_name"}).first.get.body.string
send_data s3_file, filename: "FileName.pdf", type: 'application/pdf', disposition: 'inline'
end
end
# config/routes.rb
Rails.application.routes.draw do
get 'file', to: 'file#send_pdf', defaults: { format: 'pdf' }
end
When accessing the route directly via URL, it displays the PDF fine.
When opening a link to the route in a new tab, it displays the PDF fine.
When opening a link in the same tab, the PDF data streams as text to the browser instead.
The same behavior occurs in Rails 4 and 5.
I'm probably missing something annoyingly minor here, but how can I get the open in the same tab behavior to properly display the PDF instead of streaming bytes as text?
Update 1:
Chrome gives a Failed to load PDF document error when send_pdf is modified to use send_file instead of send_data. (This error happens regardless of link click or direct route request.)
def send_pdf
# S3 download
temp_file = "#{Rails.root}/tmp/file.pdf"
File.open(temp_file,"wb") do |f|
f.write(s3_file)
f.close
end
send_file temp_file, filename: "FileName.pdf", type: 'application/pdf', disposition: 'inline'
File.delete(temp_file)
end
Have you tried send_file instead of send_data?
http://apidock.com/rails/v4.2.1/ActionController/DataStreaming/send_file

How to download file from google drive using paperclip-googledrive?

I have done file uploading on google drive but at the time of downloading got error:
ActionController::MissingFile: Cannot read file original_22_Wages372-817339(wages).pdf
I think it didn't get google drive path.
Attachment model:
has_attached_file :doc,
storage: :google_drive,
google_drive_credentials: "#{Rails.root}/config/google_drive.yml",
google_drive_options: {
public_folder_id: '0BwCp_aK6VhiaQmh5TG9Qbm0zcDQ',
path: proc { |style| "#{style}_#{id}_#{doc.original_filename}" }
}
Controller:
attachment = Attachment.find(params[:id])
send_file attachment.doc.path(:original),
filename: attachment.doc_file_name,
type: attachment.doc_content_type,
stream: 'true',
x_sendfile: true
Thanks in advance
You should read file first from your application. And then make it available for download.
attachment = Attachment.find(params[:id])
data = open(attachment.doc.url).read
send_file data,
:filename => attachment.doc_file_name,
type: attachment.doc_content_type, stream: 'true',
:x_sendfile => true
You can also make it available like :
redirect_to attachment.doc.url
But this is not a right way to do so. Because you directly opening your resources to end user.
Dinesh, try the below code it will solve your problem.
attachment = Attachment.find(params[:id])
data = attachment.doc.url(:original)
data = open(attachment.doc.url(:original))
send_file data, filename: attachment.doc_file_name,
type: attachment.doc_content_type

rails send_file and send_data sends out zero byte files

I'm trying to send a pdf back to the user but I'm having serious problem getting send_file and send_data to work. I created the pdf file as follows:
tmp = Tempfile.new('filled')
new_tmp_path = PDFPrint.fill_form_using_pdftk(template_path, tmp.path)
send_file (new_tmp_path, :filename => 'filled.pdf')
The browser prompts for a download, but the downloaded filled.pdf file has zero byte.
I have verified that new_tmp_path does contain a valid pdf (good, filled content)
I have tried this:
File.open(new_tmp_path, 'r') do |f|
send_data(f.read, :filename => "filled.pdf")
end
But this also gives me the same download->zero-byte problem, while the file on server (new_tmp_path) has perfect content.
Regards,
Try sending a simple file to see if it works
send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
Read this thread, I think it has everything you need.

Resources