Bevor jemand sagt, "duplizieren", möchte ich nur sicherstellen, dass die Leute wissen, dass ich diese Fragen bereits gelesen habe:
1) Verwendet eckig und php, nicht sicher, was hier passiert (ich kenne PHP nicht): Zip-Datei herunterladen und Dialog "Datei speichern" aus der Winkelmethode auslösen
2) Kann diese Antwort nicht erhalten, um irgendetwas zu tun: So laden Sie eine ZIP-Datei mithilfe von angle
3) Diese Person kann bereits heruntergeladen werden, was hinter dem Punkt liegt, den ich zu ermitteln versuche: Externe Zip-Datei von Winkel herunterladen, die auf einer Schaltfläche ausgelöst wird
4) Keine Antwort auf diese Frage: .ZIP-Datei vom Server in nodejs herunterladen
5) Ich weiß nicht, welche Sprache das überhaupt ist: https://stackoverflow.com/questions/35596764/Zip-file-download-using-angularjs-directive
Angesichts dieser Fragen , wenn dies noch ein Duplikat ist, entschuldige ich mich. Hier ist noch eine andere Version dieser Frage.
Mein eckiger 1.5.X-Client gibt mir eine Liste von Titeln, von denen jeder eine zugeordnete Datei hat. Mein Node 4.X/Express 4.X-Server übernimmt diese Liste, ruft die Dateispeicherorte ab, erstellt mithilfe von express-Zip von npm eine ZIP-Datei und streamt diese Datei anschließend in der Antwort zurück. Ich möchte, dass mein Client die Option "Datei herunterladen" des Browsers initiiert.
Hier ist mein 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 mit 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)
}
});
Hier ist mein successCb in meinem 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);
}
};
Der "Blob" -Teil scheint gut zu funktionieren. Bei der Überprüfung im IE-Debugger sieht es aus wie ein Datenstrom von Oktett-Informationen. Nun, ich glaube, ich muss diesen Klecks in die HTML5-Direktive aufnehmen, um das "Save File As" vom Browser aus zu initiieren. Könnte sein? Vielleicht nicht?
Da mehr als 90% unserer Benutzer IE11 verwenden, teste ich alle meine Winkel in PhantomJS (Karma) und IE. Beim Ausführen des Codes erhalte ich in einem Warnfenster den alten Fehler "Zugriff wird verweigert":
Exception: {"description":"Access is denied...<stack trace>}
Anregungen, Klarstellungen, Antworten usw. sind willkommen!
Ich habe meine bulkdownload
-Methode aktualisiert, um $window.open(...)
anstelle von $http.get(...)
zu verwenden:
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);
}
};
Ich habe das nur in IE11 getestet.
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);
Verwende das hier:
var url="YOUR Zip URL HERE";
window.open(url, '_blank');
Wie in diese Antwort angegeben, habe ich die unten stehende Javascript-Funktion verwendet und kann nun den byte[] array
-Inhalt erfolgreich herunterladen.
Funktion zum Konvertieren eines Byte-Array-Streams (String-Typ) in ein Blob-Objekt:
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;
};
Und so rufe ich diese Funktion auf und speichere das Blob-Objekt mit FileSaver.js (Daten über Angular.js $http.get
abrufen):
$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);
});
Hinweis: Ich sende den byte[] array
(Java-Server-Side) wie folgt:
byte[] myByteArray = /*generate your Zip file and convert into byte array*/ new byte[]();
return new ResponseEntity<byte[]>(myByteArray , headers, HttpStatus.OK);