Downloading image in Javascript creates corrupted file - javascript

I'm trying to download an image and write it to the disk in Javascript. The image will be delivered base64 encoded by the server. I'm then trying to decode the image, create a blob with that data and create a new URL object. The download itself works, but the output file will be corrupted and unusable. My code looks as follows:
jsonObject = JSON.parse(requestObject.getReturnData());
decoded = atob(jsonObject['DownloadFile']);
url = window.URL.createObjectURL(new Blob([decoded], { type: "image/png" }));
aElement = document.createElement('a');
aElement.style.display = 'none';
aElement.href = url;
aElement.download = 'download.' + jsonObject['DownloadType'];
document.body.appendChild(aElement);
aElement.click();
window.URL.revokeObjectURL(url);
I verified that jsonObject['DownloadFile'] contains the correct base64 representation of the image. However, it seems that there's an error when creating the blob, since its size is too big when looking at the debug console.

Related

base64 string to pdf download

I am facing issue to download pdf in SAPUI5 application. Issue is Getting base64 string from backend system but not able to convert it and display as PDF.
I am able to convert the base64 and download also but only small size.
Not able to download for larger PDF file its downloading but shows download failed.
kindly help me out
var data =" JVBERi0xLjQNJeLjz9MNCjc1MDEgMCBvYmogPDwvTGluZWFyaXplZCAxL0wgOTM2NDM1Mi9PIDc1MDMvRSAxMjE3ODgvTiA1MjIvVCA5MjE0MjgzL0ggWyA2..";
var uri = 'data:application/pdf;base64,' + atob(data);
var link = document.createElement("a");
link.href = uri;
link.style = "visibility:hidden";
link.download = object.FileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
Saving the data as a blob and setting the download link to get the data from the blog may solve your problem for large files. The most effective way in this mechanism is to get the data from your server as binary instead of Base64. It works with base64 too - but it is just a resource over kill in the blob scenario.
var data = Uint8Array.from(atob(base64_string), c => c.charCodeAt(0));
var blob = new Blob([data], {type: "octet/stream"});
var link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
...
...
As per you current solution, a hyperlink will be created with href contains data:application/pdf;base64,' + base64Data. When the hyperlink is clicked the complete URL will be opened in the browser new tab, which makes the browser to download the PFD file.
If the base64 data is bulk then the browser will take time to download PDF. Sometimes browser will be crashed OR leads to download failed error as it takes too much of time to download.
Alternative Options
Using GET_STEAM method you can download the pdf from the backend only.
Using download plugins like downloadjs, FileSaver.js, StreamSaver.js.
As per you requirement you can get different available plugins for file downloading using client-side JavaScript
Here is a sap blog entry solving your problem.
TLDR:
var base64EncodedPDF = "JVBERi0xLjcNCiW..."; // the encoded string
var decodedPdfContent = atob(base64EncodedPDF);
var byteArray = new Uint8Array(decodedPdfContent.length)
for(var i=0; i<decodedPdfContent.length; i++){
byteArray[i] = decodedPdfContent.charCodeAt(i);
}
var blob = new Blob([byteArray.buffer], { type: 'application/pdf' });
var _pdfurl = URL.createObjectURL(blob);
this._PDFViewer.setSource(_pdfurl);

Convert base64 audio to file

I have an audio blob, I then run
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
var base64data = reader.result;
//log of base64data is "data:audio/ogg; codecs=opus;base64,GkX..."
}
Now I send this data to my server and all I'm trying to do is convert to an '.ogg' file (wav or mp3 preferred). The base64 works fine when passed to an HTML audio player.
On the server I tried
fs.writeFileSync('file.ogg', base64data);
I always get the file created however it never plays, what I'm I doing wrong please?
You have binary data encoded in base64 string here. First of all you need trim data url meta info. Then you can create binary buffer from base64 string and store it to file.
fs.writeFileSync('file.ogg', Buffer.from(base64data.replace('data:audio/ogg; codecs=opus;base64,', ''), 'base64'));

Opening a file with C# as a BLOB, and downloading with JS as a BLOB

I have a PDF on my .NET Core server, which I need to somehow send across the wire as a BLOB, so that my JS AJAX request can convert it back to a PDF so it can be downloaded.
The reason for the indirection is because the file comes from my API, which is only accessed through AJAX. Due to the need for a Bearer token, I can't just use a form behind the scenes, as there's no cookie for the site created. (Weird, I know, but that's how it is presently, and I'm not looking to change that part)
So, on my C# side, I've tried several variations, shown below. ApiResponse is just a container I use that holds a bool and a string (named message) so I can tell if the request was good or not.
These are what I've been trying
return new ApiResponse(true, File.ReadAllText(path));
return new ApiResponse(true, Convert.ToBase64String(File.ReadAllBytes(path)));
return new ApiResponse(true, JsonConvert.SerializeObject(File.ReadAllBytes(path)));
And on the JS side, in the same order to parse it back out, I have:
// Get the response in object form, since it's sent as an ApiResponse
const response = JSON.parse(xmlhttp.response);
const text = response.message;
const text = atob(response.message)
const text = JSON.parse(response.message)
I've also tried things like
const text = atob(JSON.parse(response.message))
Then, with the text I'm doing this:
const blob = new Blob([text], {type: "application/pdf"});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "file.pdf";
document.body.appendChild(a);
a.click();
And this does correctly generate a file that's downloaded. However, that file is not valid: it's corrupted.
I'm pretty much stuck at this point, and I haven't been able to find something that goes from start to finish using this method to download files with Javascript. It's either the back side, or the front side, but never tied together.
So, how can I successfully send a PDF BLOB across the wire, and recreate it on the front end so it can be downloaded?
The easy answer to how to do the convert is don't.
Every modern browser supports base64 encoding natively, so there's no need to convert the data back to a BLOB before putting it into download.
Thus, the end code is:
const a = document.createElement("a");
a.href = "data:application/pdf;base64," + response.message;
a.download = "file.pdf";
document.body.appendChild(a);
a.click();

Javascript Blob anchortag download produces corrupted file

the following code downloads a file that can't be opened(corrupt) and I have absolutely no idea why. I've tried this in so many ways but it never works, it always produces a corrupt file. The original file isn't the problem because it opens fine. I'm trying to open mp4, mp3, and image files.
//$scope.fileContents is a string
$scope.fileContents = $scope.fileContents.join(",");
var blob = new Blob([$scope.fileContents], {type: $scope.file.fileDetails.type});
var dlURL = window.URL.createObjectURL(blob);
document.getElementById("downloadFile").href = dlURL;
document.getElementById("downloadFile").download = $scope.file.fileDetails.name;
document.getElementById("downloadFile").click();
window.URL.revokeObjectURL(dlURL);
You need to download the file contents as binary using an ArrayBuffer e.g.
$http.get(yourFileUrl, { responseType: 'arraybuffer' })
.then(function (response) {
var blob = new Blob([response.data], {type: $scope.file.fileDetails.type});
// etc...
});
Sources:
angular solution
plain javascript solution

How do I encode and decode a geoTiff file from a base64string?

I have a geotiff file that is being converted to a base64string upon being selected. The encoded file is then uploaded to an ASP.NET web service and then decoded and saved with a .tiff extension. The problem is that the metadata within the file is significantly altered from the original file.
JavaScript
var fr = new FileReader();
fr.onloadend = function () {
var base64string = fr.result;
var imgStr = base64string.split("base64,")[1];
App.instance.client.area.uploadMap(imgStr);
};
fr.readAsDataURL(value.rawFile);
C#/ASP.NET Web API:
byte[] imageBytes = Convert.FromBase64String(mapImage);
MemoryStream ms = new MemoryStream(imageBytes);
Image img = Image.FromStream(ms);
I'm then extrating the metadata uploaded image with the GDAL library. The image looks fine, but the metadata contained within the file is completely different. The corner coordinates are no longer accurate and there is color table information in the new file, which wasn't present in the original.
Is there any way to handle this conversion so that the bytes aren't altered?

Categories