python - send pdf as bytes in web services - javascript

I use to build a web service that response with application-json mime type.
But now I want to response a PDF as bytes, so I assume that I have to change mime type.
I will use routing but I could use flask-restful too.
The following code show the structure but I don't know how covert pdf to bytes and then send it.
#app.route('/pdf/myfile')
def pdf():
data = open("myfile.pdf", "rb").read()
# make a reponse with those bytes
return response
In the client side (angular.js) I will have this:
$http.get('/pdf/myfile', null, { responseType: 'arraybuffer' })
.success(function (data) {
var file = new Blob([data], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
});

You can use send_file or send_from_directory:
from flask import send_from_directory
#app.route('/pdf/myfile')
def pdf():
return send_from_directory('/dir/of/pdf', 'my.pdf')
By default this will send the file inline and browsers will probably render the PDF itself. If you set as_attachment=True the file will be presented as an attachment, and the browser will throw up a "save as" dialog box.
send_file gives you more control over things such as mime types and caching. The defaults should work well.

Related

Download ANSI zip file in front end, generated by C# back end

I have a C# backend generating a zip file in memory (with System.IO.Compression) and sending it to my front end. If I download the zip file before sending it, it is working well and is in ANSI encoding (found on notepad++).
This is how I return my file currently, I have tried many different ways to do it, such as simply returning a file without headers, but right now it looks like this :
[HttpPost]
[Route("GetUserWorkContext")]
public async Task<IActionResult> GetUserWorkContext([FromBody] GetUserWorkContextRequest request, [FromServices] IExportManager exportManager)
{
var zipStream = await exportManager.GetUserWorkContext(userId, request.IncludeArchived);
HttpContext.Response.Headers.Add("Content-Disposition", "attachment; filename = test.zip; charset=Windows-1252");
HttpContext.Response.Headers.Add("Content-Length", zipStream.ToArray().Length.ToString());
return File(zipStream.ToArray(), "application/octet-stream");
}
It seems that no matter how I download the file with Javascript (front-end), it is saved with utf8 encoding (found with notepad++ again). I tried using js-file-download ( https://www.npmjs.com/package/js-file-download ) or creating blobs, but anything I end up downloading is encoded in utf8.
How should I go about downloading this file in Javascript without corrupting the archive ?
Here is my current attempt in Javascript, using a piece of code I found here (JavaScript blob filename without link) to download the file :
function getUserWorkContext({ includeArchived }) {
return new Promise(function () {
Axios.post('/api/Export/GetUserWorkContext', {includeArchived})
.then((response) => {
if(response.data){
var blobObject = new Blob([response.data], {type: 'application/zip;charset=Windows-1252'});
downloadFile(blobObject, "test.zip");
}
})
}
function downloadFile(file, fileName) {
if (navigator.msSaveBlob) { // For ie and Edge
return navigator.msSaveBlob(file, fileName);
}
else {
let link = document.createElement('a');
link.href = window.URL.createObjectURL(file);
link.download = fileName;
document.body.appendChild(link);
link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
link.remove();
window.URL.revokeObjectURL(link.href);
}
}
Note : the actual zip is 3,747KB where as the download zip from Javascript is always much bigger, in this case : 6,917KB.
This is a problem with axios:
I guess, you should use blob or arraybuffer as responseType for axios.
{ responseType: 'blob' }
// responseType indicates the type of data that the server will
respond with // options are: 'arraybuffer', 'document', 'json',
'text', 'stream' // browser only: 'blob'
responseType: 'json' // default
Check this answer: https://stackoverflow.com/a/60461828/2487565
=== 8< ======================= previous version ======================= 8< ===
Your Content-Disposition header is wrong. There is no charset parameter for Content-Disposition header.
Check the docs: MDN HTTP Content-Disposition
That's why your file is still sent in UTF-8, since your charset parameter has no effect.
To use UTF-8:
Delete both Content- headers from C# and the charset parameter from JavaScript
var blobObject = new Blob([response.data], {type: 'application/zip'});
If you really need to use Windows-1252, you can try to set it with the content type parameter.
return File(zipStream.ToArray(), "application/octet-stream;charset=Windows-1252");
Check this also: Charset Encoding in ASP.NET Response
By the way, UTF-8 is the preferred charset encoding: W3 QA choosing encodings
And, yes #nikneem, there is no need in the Content-Disposition and Content-Length headers. They will be generated automatically.

Save File through JQuery AJAX Call

I am using JQuery to send an AJAX request to a Node server (using Hapi). The server responds with a PDF file correctly, but I am trying to save the file locally. The catch is that the PDF should only return if the POST sent the right data. It's "protected" in other words and I don't want to just expose it publicly.
Frontend code:
$.get('http://localhost:3000').done(function (data) {
console.log(data);
});
Backend code:
server.route({
method: 'GET',
path: '/',
handler: async (request, h) => {
return h.file('./static/sample.pdf', {
mode: 'attachment',
filename: 'sample.pdf'
})
}
});
I receive the data but nothing happens in the front-end UI. How can I download the PDF that is sent automatically?
You can achieve that with html5 using
Download it!
Notice that this works only for same-origin URLs, or the blob: and data: schemes. And this gets overridden by the Content-Disposition header from the server.
If you want to do this programatically you could do this
const element = document.createElement("a")
element.setAttribute(
"href",
// you could also use base64 encoding here like data:application/pdf;base64,
"data:text/plain;charset=utf-8," + encodeURIComponent('pdf binary content here')
)
element.setAttribute("download", "file.pdf")
element.style.display = "none"
document.body.appendChild(element)
element.click()
document.body.removeChild(element)
Anyway this is only a useful method if u want to create/modify the downloaded data from the client side, but if u are getting it as it is from the server side then its better just to open a new url, letting the browser handle it.

Blob from PDF File

I receive a PDF using Angular Http from an external API with using Content Type: application/pdf. So a simple Get Request, nothing fancy.
Now I need to convert this into a Blob object. However it doesn't seem to work.
How can I accomplish this in JavaScript?
Somehow directly saying let blobFile = new Blob(result) or let blobFile = new Blob([result]) doesn't seem to work.
You should be able to do the conversion when you do the request if the Content-type is application/pdf:
yourServiceMethod(): Promise<Blob> {
return this.httpClient.get(your-url, { responseType: 'blob' }).toPromise();
}
from there, you can use a utility like file-saver to complete the download process to the client's machine:
import * as FileSaver from 'file-saver';
onDownload(): void {
this.yourService.yourServiceMethod().then(file => {
FileSaver.saveAs(file, fileName);
});
}

Creating Blob object from raw file downloaded from server with $http.

On server there is url with files stored.
Url is http://website.com/abc
I do $http get on this url.
$http.get(url, { responseType: "arraybuffer" });
I want to create Blob object from this. I am sure that object is of type png, because it had this extension before upload and it shows properly.
new Blob(result.data, {type: "image/png"});
I get message:
Failed to construct 'Blob': The 1st argument is neither an array, nor does it have indexed properties.
Response from server http://website.com/abc GET in developer console looks like:
ÿØÿàJFIFÿþ;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 60
ÿÛC

 ' .)10.)-,3:J>36F7,-#WAFLNRSR2>ZaZP`JQROÿÛC&&O5-5OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOÿÂÒ"ÿÄÿÄÿÚæå2ag\Ý#úDê3[Zdfc5±Ô¢¬æ)K<`¤l2¸ÊánYR±aA`Í%RÈfbz!¤tÞÑ-µd7ZªÀ[hz¨f¥>©cAV¬{3á R³F0 W>~c³"ðÈìøÖ²ÇBÙ³±+
½ò9tµ°õ
I tried to set Blob type to application/octet-stream and also do $http.get without specified responseType.
How can I create a proper Blob file?
I need Blob File, to create File object which is an entry data to implemented logic to display files in slideshow with modals. I have implemented logic for files of type File, which were created by input forms - implementation was done for a need before uploading to server. Now it turns out that server doesn't return same files to me, but return only urls of files, which created an idea to convert from url to File in order to dont repeat in that logic.
Try
$http.get(url, { responseType: "blob" });
or
// missing `[]` at `js` at Question
new Blob([result.data], {type: "image/png"});
Note XMLHttpRequest responseType could also be set to "blob", see How to build PDF file from binary string returned from a web-service using javascript

Download excel file in javascript from Rest API response content-disposition outputs [Object, Object]

I want to download a excel file from my angularJs code. Where i made a http post request to Java Rest API and returned the file with header
"Content-Disposition" : "attachment; filename=\"new_excel_file.xlsx\""
Java Code
#Post
#Path("/excel/trekResult")
#Produces("application/vnd.ms-excel")
public Response getResultsReport(#HeaderParam(Constants.ID) Long userId, #QueryParam(Constants.COMPANY_TREK_ID) Integer companyTrekId) {
String CONTENT_DESPOSITION = "Content-Disposition";
String CONTENT_ATTACHEMENT = "attachment; filename=\"new_excel_file.xlsx\"";
//Generates a excel file in local file system
File excelFile = misHelper.writeToFile(workBook, mis, userId, "trek-results");
return Response.ok().entity((Object)excelFile).
header(CONTENT_DESPOSITION, CONTENT_ATTACHEMENT).build();
}
On Javascript Side
myService.exportResult($scope.companyTrek.id).then(function(result) {
if(result !== undefined || result !== '') {
var blob = new Blob([result], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
var objectUrl = URL.createObjectURL(blob);
saveAs(blob, 'Trek-Results-'+fetchCurrentDate()+ '.xlsx');
}
}
Used FileSaver.js to save file.
The output file is [Object, Object]
Tested The locally generated file.
Here is a similar question for reference that didn't help me.
receive an excel file as response in javascript from a Rest service
I just noticed the Mime types are different on Java server vs Angular client.
This link shows the different MIME types related to spreadsheets.
Try making them consistent and seeing if that fixed it.
There was also this way without mishelper.

Categories

Resources