There is a program (in asp.net mvc) on browser that connect to scanner, Scan document and show it as images.
enter image description here
Src of image is like below:
data:application/octet-stream;base64,Qk0m2wEAAAAAAD4AAAAoAAAAOAMAAJEEAAABA//////////////////////wAGA/wAYMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAg13xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
Now, I want convert all of images to one pdf and attach it to a file upload.
Could you help me please?
Please use the below code to convert Base64 to PDF with the client side JavaScript. Pass the base64 data to the function base64ToArrayBuffer
function base64toPDF(data) {
var bufferArray = base64ToArrayBuffer(data);
var blobStore = new Blob([bufferArray], { type: "application/pdf" });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blobStore);
return;
}
var data = window.URL.createObjectURL(blobStore);
var link = document.createElement('a');
document.body.appendChild(link);
link.href = data;
link.download = "file.pdf";
link.click();
window.URL.revokeObjectURL(data);
link.remove();
}
function base64ToArrayBuffer(data) {
var bString = window.atob(data);
var bLength = bString.length;
var bytes = new Uint8Array(bLength);
for (var i = 0; i < bLength; i++) {
var ascii = bString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
};
You need some kind of JavaScript PDF library to do this.
jsPDF for instance has a addImage() method (https://rawgit.com/MrRio/jsPDF/master/docs/module-addImage.html) which accepts a base64 string as input
Related
So here in C# code i am sending corgi to client which has corgiBabies. Using ClosedXml here.
var wbCorgiBabiesTemplate = new XLWorkbook();
var wsCoriBabiesAmendementTemplate = wbCorgiBabiesTemplate.Worksheets.Add(" Work Sheet Corgi baby Template");
wsCoriBabiesAmendementTemplate.Cell("A1").Value = "Corgi Parent";
wsCoriBabiesAmendementTemplate.Cell("B1").Value = "Corgi Child";
wsCoriBabiesAmendementTemplate.Cell("A2").Value = "Petunia";
wsCoriBabiesAmendementTemplate.Cell("B2").Value = "Khaleesi";
using (var ms = new MemoryStream())
{
wbCorgiBabiesTemplate.SaveAs(ms);
byte[] Corgibabies = ms.ToArray();
}
corgi.Corgibabies = System.Text.Encoding.UTF8.GetString(Corgibabies);
return corgi;
After that in Client i want to open corgibabies in excel sheet but the conversion here is wrong somewhere i think that excel sheet doesn't open correctly.
var fileName = 'CorgiBabies.xlsx';
dataAccessService.get('corgi')
.then(function(response) {
let utf8Encode = new TextEncoder();
var strBytes = utf8Encode.encode(response.corgiBabies);
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var file = new Blob([strBytes], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
var fileURL = window.URL.createObjectURL(file);
a.href = fileURL;
a.download = fileName;
a.click();
})
Below what excel sheet gives me error in image
Assuming you're on .Net Core+ (otherwise you can find the System.Buffers Nuget package for .Net standard or framework), on server side try
using System.Buffers;
using System.Buffers.Text;
and insert
var outputBuffer = new Span<byte>();
var status = Base64.EncodeToUtf8(Corgibabies, outputBuffer, out var consumed, out var written);
// sanity check
// if (status != OperationStatus.Done) throw new Exception();`
// do the above just before replacing
// System.Text.Encoding.UTF8.GetString(Corgibabies);
// with
System.Text.Encoding.UTF8.GetString(outputBuffer);
Now I'm pretty certain that will ensure that the server responds with what the client should expect but I'm not set up to test the Javascript side of things (yet). In the meantime let me know if this helps you make progress.
PS1: the error in your original code was the implicit assumption that Corgibabies is an array containing the bytes of a UTF8 encoded string. It actually contains the raw bytes of what would normally be an .xlsx file on disk. What is needed is to make that into text (Base64 encoding) and ensure that text is UTF8. Obviously in the Javascript you need to do the reverse - UTF8 Base64 to binary, save to disk, open in Excel...
Instead of returning string as the Content, you can make it work with File.
public ActionResult Get()
{
var wbCorgiBabiesTemplate = new XLWorkbook();
var wsCoriBabiesAmendementTemplate = wbCorgiBabiesTemplate.Worksheets.Add(" Work Sheet Corgi baby Template");
wsCoriBabiesAmendementTemplate.Cell("A1").Value = "Corgi Parent";
wsCoriBabiesAmendementTemplate.Cell("B1").Value = "Corgi Child";
wsCoriBabiesAmendementTemplate.Cell("A2").Value = "Petunia";
wsCoriBabiesAmendementTemplate.Cell("B2").Value = "Khaleesi";
wbCorgiBabiesTemplate.SaveAs("new.xlsx");
var ms = new MemoryStream();
wbCorgiBabiesTemplate.SaveAs(ms);
ms.Position = 0;
var fileName = "CorgiBabies.xlsx";
return File(ms, "application/octet-stream", fileName);
}
Api call:
or
fetch('https://localhost:7135/api/downloadExcel')
.then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// the filename you want
a.download = 'CorgiBabies.xlsx';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
.catch(() => alert('oh no!'));
Ref: git
ClosedXML has several extensions that will help you acheive what you need :
ClosedXML.Extensions.AspNet
ClosedXML.Extensions.Mvc
ClosedXML.Extensions.WebApi
You can install the appropriate extension for your project, to help give you a fast access to download the workbook. You can also save the file on disk, and pass the file link (path) to JavaScript, and continue your work on the file from JavaScript.
if you need to know how you would let the user download the file from ASP.NET,
then you can do this :
Simple workbook :
C#: ASP.NET MVC
[HttpGet]
public ActionResult Download(string fileName)
{
// create workbook
var workbook = new XLWorkbook();
var sheet = workbook.Worksheets.Add("Worksheet 1");
sheet.Cell("A1").Value = "A1";
sheet.Cell("B1").Value = "B1";
sheet.Cell("A2").Value = "A2";
sheet.Cell("B2").Value = "B2";
// get workbook bytes
byte[] workbookBytes;
using (var memoryStream = new MemoryStream())
{
workbook.SaveAs(memoryStream);
workbookBytes = memoryStream.ToArray();
}
return File(workbookBytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName);
}
C#: ASP.NET Web Forms
public void Export(HttpResponse response, string fileName)
{
// create workbook
var workbook = new XLWorkbook();
var sheet = workbook.Worksheets.Add("Worksheet 1");
sheet.Cell("A1").Value = "A1";
sheet.Cell("B1").Value = "B1";
sheet.Cell("A2").Value = "A2";
sheet.Cell("B2").Value = "B2";
HttpResponse httpResponse = response;
httpResponse.Clear();
httpResponse.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
httpResponse.AddHeader("content-disposition", $"attachment;filename=\"{fileName}.xlsx\"");
using (var memoryStream = new MemoryStream())
{
workbook.SaveAs(memoryStream);
memoryStream.WriteTo(httpResponse.OutputStream);
}
httpResponse.End();
}
the above examples will directly download the file into the client device. However, if you want to pass the workbook bytes to the JavaScript, you will need to convert it to base64 string and pass it to the JavaScript like so :
var base64String = Convert.ToBase64String(workbookBytes);
Then from JavaScript decode it to Uint8Array :
/*
JavaScript
*/
// get base64 string array and decoded it
var data = atob(serverSideResult);
var array = new Array(data.length);
for (var i = 0; i < data.length; i++) {
array[i] = data.charCodeAt(i);
}
// final result
var dataUint8Array = new Uint8Array(array);
now you can work with dataUint8Array as normal Uint8Array.
if you want to pass it back to the server-side, you can convert the array to base64 string, and pass it to the server-side like so :
/*
JavaScript
*/
let binaryString = ''
for (var i = 0; i < dataUint8Array.byteLength; i++) {
binaryString += String.fromCharCode(dataUint8Array[i]);
}
//pass base64Result to the server-side (C#)
var base64Result = window.btoa(binaryString);
then from C# you just need to convert it back to array from base64 string like so :
var bytes = Convert.FromBase64String(dataReceivedFromJavaScript);
where bytes would be byte[].
I'm getting excel data encoded as base64 string from backend. I want to decode this data and download the excel file in the browser. I'm using vuejs as my frontend. Also if I were to show this data in table format on the frontend, how can I go about doing that? Thanks in advance for the response.
This is what I have tried-
public downloadfile() {
var data = window.atob("string");
this.save("file", data, ".xls");
}
public save(name: any, data: any, type: any) {
var bytes = new Array(data.length);
console.log("here", bytes);
for (var i = 0; i < data.length; i++) {
bytes[i] = data.charCodeAt(i);
}
data = new Uint8Array(bytes);
var blob = new Blob([data], { type: type });
console.log(blob);
let objectURL = window.URL.createObjectURL(blob);
let anchor = document.createElement("a");
anchor.href = objectURL;
anchor.download = name;
anchor.click();
URL.revokeObjectURL(objectURL);
}
I have a run button on clicking that downloadfile runs. and a file.txt gets downloaded. What am I doing wrong here? If I rename the file format to xls, that file shows correct data.
You need a browser Javascript library that understands excel format. I have used sheetjs with good success in the past.
I have an AJAX call which calls a secure PHP API call that generates PDF file data (on the fly, no actual file) and returns it. How can I use this PDF file data in javascript/jquery to create and download a PDF file to the user?
I've originally tried setting the ajax call's heads to that of a PDF, but obviously you can't download files via ajax.
To automatically download a file from ajax call you can do the following. In my example I returned an object that contained the file name, mime type, and Base64 data but maybe this can give you an idea on how to do what you are looking for.
PostDTO('/ReportService.asmx/DownloadReport', dto, function (result) {
var a = document.createElement('a');
if (window.URL && window.Blob && ('download' in a) && window.atob) {
// Do it the HTML5 compliant way
var blob = base64ToBlob(result.FileDataBase64, result.MimeType);
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = result.Filename;
a.click();
window.URL.revokeObjectURL(url);
}
});
function base64ToBlob(base64, mimetype, slicesize) {
if (!window.atob || !window.Uint8Array) {
// The current browser doesn't have the atob function. Cannot continue
return null;
}
mimetype = mimetype || '';
slicesize = slicesize || 512;
var bytechars = atob(base64);
var bytearrays = [];
for (var offset = 0; offset < bytechars.length; offset += slicesize) {
var slice = bytechars.slice(offset, offset + slicesize);
var bytenums = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
bytenums[i] = slice.charCodeAt(i);
}
var bytearray = new Uint8Array(bytenums);
bytearrays[bytearrays.length] = bytearray;
}
return new Blob(bytearrays, { type: mimetype });
};
You can download file from ajax.
I did it from an angular application.
The idea :
Get the file data and ask a response type "arrayBuffer"
Be sure the data response are not transformed by your framework (as it is with angular)
Create a blob : var blob = new Blob([data], {type: 'application/pdf');//check type
Create an url : var url = URL.createObjectURL(blob);
Open the url : window.open(url);
You can verify the blob generated via the console, the blob url is showed. That url must open your pdf.
I have used HTML file reader API to read the file,
and i got the below result
data:application/pdf;base64,JVBERi0xLjYNJeLjz9MNCjE2OSAwIG9iaiA8PC9MaW5lYXJpemVkIDEvTCAyMDgwNTMxL08gMTczL0UgMjg1ODM3L04gMjQvVCAyMDc3MDkyL0ggWyAxMTM2IDc1OV0+Pg1lbmRvYmoNICAgICAgICAgIA14cmVmDTE2OSA0Mg0wMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDE4OTUgMDAwMDAgbg0KMDAwMDAwMjAzMSAwMDAwMCBuDQowMDAwMDAyMTY0IDAwMDAwIG4NCjAwMDAwMDIzMTkgMDAwMDAgbg0KMDAwMDAwMjgzOCAwMDAwMCBuDQowMDAwMDAyODY0IDAwMDAwIG4NCjAwMDAwMDM3OTAgMDAwMDAgbg0KMDAwMDAwNDMyNCAwMDAwMCBuDQowMDAwMDA0NDE1IDAwMDAwIG4NCjAwMDAwMDU2MDcgMDAwMDAgbg0KMDAwMDAwNTY1MiAwMDAwMCBuDQowMDAwMDA1Njc3IDAwMDAwIG4NCjAwMDAwMDU3OTUgMDAwMDAgbg0KMDAwMDAwNTg0NSAwMDAwMCBuDQowMDAwMDA1ODcwIDAwMDAwIG4NCjAwMDAwMDU5ODYgMDAwMDAgbg0KMDAwMDAwNzQxOSAwMDAwMCBuDQowMDAwMDA3Nzk4IDAwMDAwIG4NCjAwMDAwMDgxMDQgMDAwMDAgbg0KMDAwMDAwODQxMyAwMDAwMCBuDQowMDAwMDA4OTQ0IDAwMDAwIG4NCjAwMDAwMDk2NTAgMDAwMDAgbg0KMDAwMDAxMDA1NiAwMDAwMCBuDQowMDAwMDEwMjIxIDAwMDAwIG4NCjAwMDAwMTA1NDIgMDAwMDAgbg0KMDAwMDAxMDc1MCAwMDAwMCBuDQowMDAwMDExMDM1IDAwMDAwIG4NCjAwMDAwMTEwOTYgMDAwMDAgbg0KMDAwMDAxMTQxMiAwMDAwMCBuDQo...AwMDAwIG4NCjAwMDIwNTkxMzggMDAwMDAgbg0KMDAwMjA2MjUxMyAwMDAwMCBuDQowMDAyMDYyOTE4IDAwMDAwIG4NCjAwMDIwNjI5NjYgMDAwMDAgbg0KMDAwMjA2MzMyNSAwMDAwMCBuDQowMDAyMDYzNDEyIDAwMDAwIG4NCjAwMDIwNjM2NDggMDAwMDAgbg0KMDAwMjA2NDU0NiAwMDAwMCBuDQowMDAyMDY1NTU0IDAwMDAwIG4NCjAwMDIwNjU1NzMgMDAwMDAgbg0KMDAwMjA2NTY1MCAwMDAwMCBuDQowMDAyMDY1Njg3IDAwMDAwIG4NCjAwMDIwNjU3MTggMDAwMDAgbg0KMDAwMjA2NTc4OSAwMDAwMCBuDQowMDAyMDY1OTIxIDAwMDAwIG4NCjAwMDIwNjYwNTMgMDAwMDAgbg0KMDAwMjA2NjE0NSAwMDAwMCBuDQowMDAyMDY2MjAyIDAwMDAwIG4NCjAwMDIwNjk5MDEgMDAwMDAgbg0KMDAwMjA2OTk1MSAwMDAwMCBuDQowMDAyMDcwMDE3IDAwMDAwIG4NCjAwMDIwNzAwNDkgMDAwMDAgbg0KMDAwMjA3MDA5OCAwMDAwMCBuDQowMDAyMDcwMTQyIDAwMDAwIG4NCjAwMDIwNzAxODggMDAwMDAgbg0KMDAwMjA3MDIxMCAwMDAwMCBuDQowMDAyMDcwMjc5IDAwMDAwIG4NCjAwMDIwNzAzMTcgMDAwMDAgbg0KMDAwMjA3MDM3NSAwMDAwMCBuDQowMDAyMDcwNDk5IDAwMDAwIG4NCjAwMDIwNzA1MzEgMDAwMDAgbg0KMDAwMjA3MDU1MiAwMDAwMCBuDQowMDAyMDcwNTc4IDAwMDAwIG4NCjAwMDIwNzY4NDMgMDAwMDAgbg0KdHJhaWxlcg08PC9TaXplIDE2OS9FbmNyeXB0IDE3MCAwIFI+Pg1zdGFydHhyZWYNMTE2DSUlRU9GDQ==
How to write a file and force download the same file using the above string?
Warning: I don't have IE available to test with, but this was based off code that DOES work under IE.
My DataURL is an image so I had to change out the header. You might not have to with your header -- but I left the code in place so you could see how it was done.
Thanks to IE, you need two different processes.
On IE, you convert your DataURI to a blob then download the blob.
On everything else, you would just download the URI itself.
document.getElementById("d_button").addEventListener("click", download);
var filename="testfile";
// FROM http://stackoverflow.com/questions/12168909/blob-from-dataurl
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {
type: mimeString
});
return blob;
// Old code
// var bb = new BlobBuilder();
// bb.append(ab);
// return bb.getBlob(mimeString);
}
const dataURI = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
function download() {
if (window.navigator.msSaveBlob) { // for IE
const blob = dataURItoBlob(dataURI);
window.navigator.msSaveBlob(blob, `${filename}.png`);
return;
}
let dt = dataURI;
/* Change MIME type to trick the browser to downlaod the file instead of displaying it */
dt = dt.replace(/^data:image\/[^;]*/, "data:application/octet-stream");
/* In addition to <a>'s "download" attribute, you can define HTTP-style headers */
dt = dt.replace(/^data:application\/octet-stream/, `data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=${filename}.png`);
this.href = dt;
}
Download this
I got answer using <a> tag force the download the file.
var element = document.createElement('a');
element.setAttribute('href',text );
element.setAttribute('download', filename);
element.setAttribute('target', '_blank');
element.style.display = 'none';
document.body.appendChild(element);
$("#page_header").removeClass('loader');
element.click();
I got another answer using force the download the file.
using this link install file saver (https://www.npmjs.com/package/file-saver)
result : 'data:application/pdf;base64,JVBERi0xLjYNJeLjz9MNCjE2OSAwIG9iaiA8PC9MaW5lYXJpemVkIDEvTCAyMDgwNTMxL08gMTczL0UgMjg1ODM3L04gMjQvVCAyMDc3MDkyL0ggWyAxMTM2IDc1OV0+Pg1lbmRvYmoNICAgICAgICAgIA14cmVmDTE2OSA0Mg0wMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDE4OTUgMDAwMDAgbg0KMDAwMDAwMjAzMSAwMDAwMCBuDQowMDAwMDAyMTY0IDAwMDAwIG4NCjAwMDAwMDIzMTkgMDAwMDAgbg0KMDAwMDAwMjgzOCAwMDAwMCBuDQowMDAwMDAyODY0IDAwMDAwIG4NCjAwMDAwMDM3OTAgMDAwMDAgbg0KMDAwMDAwNDMyNCAwMDAwMCBuDQowMDAwMDA0NDE1IDAwMDAwIG4NCjAwMDAwMDU2MDcgMDAwMDAgbg0KMDAwMDAwNTY1MiAwMDAwMCBuDQowMDAwMDA1Njc3IDAwMDAwIG4NCjAwMDAwMDU3OTUgMDAwMDAgbg0KMDAwMDAwNTg0NSAwMDAwMCBuDQowMDAwMDA1ODcwIDAwMDAwIG4NCjAwMDAwMDU5ODYgMDAwMDAgbg0KMDAwMDAwNzQxOSAwMDAwMCBuDQowMDAwMDA3Nzk4IDAwMDAwIG4NCjAwMDAwMDgxMDQgMDAwMDAgbg0KMDAwMDAwODQxMyAwMDAwMCBuDQowMDAwMDA4OTQ0IDAwMDAwIG4NCjAwMDAwMDk2NTAgMDAwMDAgbg0KMDAwMDAxMDA1NiAwMDAwMCBuDQowMDAwMDEwMjIxIDAwMDAwIG4NCjAwMDAwMTA1NDIgMDAwMDAgbg0KMDAwMDAxMDc1MCAwMDAwMCBuDQowMDAwMDExMDM1IDAwMDAwIG4NCjAwMDAwMTEwOTYgMDAwMDAgbg0KMDAwMDAxMTQxMiAwMDAwMCBuDQo...AwMDAwIG4NCjAwMDIwNTkxMzggMDAwMDAgbg0KMDAwMjA2MjUxMyAwMDAwMCBuDQowMDAyMDYyOTE4IDAwMDAwIG4NCjAwMDIwNjI5NjYgMDAwMDAgbg0KMDAwMjA2MzMyNSAwMDAwMCBuDQowMDAyMDYzNDEyIDAwMDAwIG4NCjAwMDIwNjM2NDggMDAwMDAgbg0KMDAwMjA2NDU0NiAwMDAwMCBuDQowMDAyMDY1NTU0IDAwMDAwIG4NCjAwMDIwNjU1NzMgMDAwMDAgbg0KMDAwMjA2NTY1MCAwMDAwMCBuDQowMDAyMDY1Njg3IDAwMDAwIG4NCjAwMDIwNjU3MTggMDAwMDAgbg0KMDAwMjA2NTc4OSAwMDAwMCBuDQowMDAyMDY1OTIxIDAwMDAwIG4NCjAwMDIwNjYwNTMgMDAwMDAgbg0KMDAwMjA2NjE0NSAwMDAwMCBuDQowMDAyMDY2MjAyIDAwMDAwIG4NCjAwMDIwNjk5MDEgMDAwMDAgbg0KMDAwMjA2OTk1MSAwMDAwMCBuDQowMDAyMDcwMDE3IDAwMDAwIG4NCjAwMDIwNzAwNDkgMDAwMDAgbg0KMDAwMjA3MDA5OCAwMDAwMCBuDQowMDAyMDcwMTQyIDAwMDAwIG4NCjAwMDIwNzAxODggMDAwMDAgbg0KMDAwMjA3MDIxMCAwMDAwMCBuDQowMDAyMDcwMjc5IDAwMDAwIG4NCjAwMDIwNzAzMTcgMDAwMDAgbg0KMDAwMjA3MDM3NSAwMDAwMCBuDQowMDAyMDcwNDk5IDAwMDAwIG4NCjAwMDIwNzA1MzEgMDAwMDAgbg0KMDAwMjA3MDU1MiAwMDAwMCBuDQowMDAyMDcwNTc4IDAwMDAwIG4NCjAwMDIwNzY4NDMgMDAwMDAgbg0KdHJhaWxlcg08PC9TaXplIDE2OS9FbmNyeXB0IDE3MCAwIFI+Pg1zdGFydHhyZWYNMTE2DSUlRU9GDQ=='
file_name : 'sample.jpg'
fileType : 'image/jpeg'
**Function Call**
this.urltoFile(result, file_name, fileType)
.then(function(file){
var blob = new Blob ([file], {type: fileType});
FileSaver.saveAs(blob, file_name);
this.loading = false;
});
**function definition**
urltoFile(url, filename, mimeType){
return (fetch(url)
.then(function(res){return res.arrayBuffer();})
.then(function(buf){return new File([buf], filename, {type:mimeType});})
)},
Before somebody says, "duplicate", I just want to make sure, that folks know, that I have already reviewed these questions:
1) Uses angular and php, not sure what is happening here (I don't know PHP): Download zip file and trigger "save file" dialog from angular method
2) Can't get this answer to do anything: how to download a zip file using angular
3) This person can already download, which is past the point I'm trying to figure out:
Download external zip file from angular triggered on a button action
4) No answer for this one:
download .zip file from server in nodejs
5) I don't know what language this even is:
https://stackoverflow.com/questions/35596764/zip-file-download-using-angularjs-directive
Given those questions, if this is still a duplicate, I apologize. Here is, yet, another version of this question.
My angular 1.5.X client gives me a list of titles, of which each have an associated file. My Node 4.X/Express 4.X server takes that list, gets the file locations, creates a zip file, using express-zip from npm, and then streams that file back in the response. I then want my client to initiate the browser's "download a file" option.
Here's my client code (Angular 1.5.X):
function bulkdownload(titles){
titles = titles || [];
if ( titles.length > 0 ) {
$http.get('/query/bulkdownload',{
params:{titles:titles},
responseType:'arraybuffer'
})
.then(successCb,errorCb)
.catch(exceptionCb);
}
function successCb(response){
// This is the part I believe I cannot get to work, my code snippet is below
};
function errorCb(error){
alert('Error: ' + JSON.stringify(error));
};
function exceptionCb(ex){
alert('Exception: ' + JSON.stringify(ex));
};
};
Node (4.X) code with express-zip, https://www.npmjs.com/package/express-zip:
router.get('/bulkdownload',function(req,resp){
var titles = req.query.titles || [];
if ( titles.length > 0 ){
utils.getFileLocations(titles).
then(function(files){
let filename = 'zipfile.zip';
// .zip sets Content-Type and Content-disposition
resp.zip(files,filename,console.log);
},
_errorCb)
}
});
Here's my successCb in my client code (Angular 1.5.X):
function successCb(response){
var URL = $window.URL || $window.webkitURL || $window.mozURL || $window.msURL;
if ( URL ) {
var blob = new Blob([response.data],{type:'application/zip'});
var url = URL.createObjectURL(blob);
$window.open(url);
}
};
The "blob" part seems to work fine. Checking it in IE's debugger, it does look like a file stream of octet information. Now, I believe I need to get that blob into the some HTML5 directive, to initiate the "Save File As" from the browser. Maybe? Maybe not?
Since 90%+ of our users are using IE11, I test all of my angular in PhantomJS (Karma) and IE. When I run the code, I get the old "Access is denied" error in an alert window:
Exception: {"description":"Access is denied...<stack trace>}
Suggestions, clarifications, answers, etc. are welcome!
Use this one:
var url="YOUR ZIP URL HERE";
window.open(url, '_blank');
var zip_file_path = "" //put inside "" your path with file.zip
var zip_file_name = "" //put inside "" file name or something
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = zip_file_path;
a.download = zip_file_name;
a.click();
document.body.removeChild(a);
As indicated in this answer, I have used the below Javascript function and now I am able to download the byte[] array content successfully.
Function to convert byte array stream (type of string) to blob object:
var b64toBlob = function(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
};
An this is how I call this function and save the blob object with FileSaver.js (getting data via Angular.js $http.get):
$http.get("your/api/uri").success(function(data, status, headers, config) {
//Here, data is type of string
var blob = b64toBlob(data, 'application/zip');
var fileName = "download.zip";
saveAs(blob, fileName);
});
Note: I am sending the byte[] array (Java-Server-Side) like this:
byte[] myByteArray = /*generate your zip file and convert into byte array*/ new byte[]();
return new ResponseEntity<byte[]>(myByteArray , headers, HttpStatus.OK);
I updated my bulkdownload method to use $window.open(...) instead of $http.get(...):
function bulkdownload(titles){
titles = titles || [];
if ( titles.length > 0 ) {
var url = '/query/bulkdownload?';
var len = titles.length;
for ( var ii = 0; ii < len; ii++ ) {
url = url + 'titles=' + titles[ii];
if ( ii < len-1 ) {
url = url + '&';
}
}
$window.open(url);
}
};
I have only tested this in IE11.