First I created a pdf with WickedPDF.
pdf_string = WickedPdf.new.pdf_from_string(
ActionController::Base.new.render_to_string(template: 'v1/invoices/invoice_template', filename: 'test.pdf')
)
invoice.attachment.attach(
io: StringIO.new(pdf_string),
filename: 'test.pdf',
content_type: 'application/pdf'
)
My app is setup to store the files on s3 on prod and locally in dev. For testing I also used s3 in dev to verify that my pdf is getting generated and saved correctly. So after it has been generated I am able to log into aws and download my invoice. Everything displays just fine.
Now the problem I have is trying to download my invoice. When I download it, my pdf is just blank.
I have a download method that looks like this:
response.headers['Content-Type'] = @invoice.attachment.content_type
response.headers['Content-Disposition'] = "inline; #{@invoice.attachment.filename}"
response.headers['filename'] = @invoice.filename
@invoice.attachment.download do |chunk|
response.stream.write(chunk)
end
I also tried
send_data @invoice.attachment.download, filename: @invoice.filename
and my frontend (react) uses axios to download it:
const downloadInvoice = (id) => {
axios.get(`/v1/invoices/${id}/download`)
.then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', response.headers.filename);
document.body.appendChild(link);
link.click();
})
.catch(() => {});
};
I am a little confused to why my downloaded pdf is blank. If I open it in my storage folders it displays just fine. There seems to be an issue with how I download it.
What works is if I create a presigned URL for S3 with:
s3 = Aws::S3::Resource.new(client: aws_client)
bucket = s3.bucket('bucket-name')
obj = bucket.object("@invoice.attachment.attachment.blob.key)
url = obj.presigned_url(:get)
I can send that url back to the frontend and open it in a new tab to view the pdf. But this is not what I want...
Thanks for any help!
In case anyone is interested in this or runs into the same issue. I hope this will save you some time!
The problem is with the axios request.
Instead of:
axios.get(`/v1/invoices/${id}/download`)
use
axios.get(`/v1/invoices/${id}/download`, { responseType: 'arraybuffer' })