Herunterladen von Dateien (mit Axios und Sicherheit)
Dies ist sogar noch komplexer, wenn Sie Dateien mit Axios und einigen Sicherheitsmaßnahmen herunterladen möchten. Um zu verhindern, dass andere zu viel Zeit damit verbringen, dies herauszufinden, möchte ich Sie durch diese Sache führen.
Sie müssen 3 Dinge tun:
1. Configure your server to permit the browser to see required HTTP headers
2. Implement the server-side service, and making it advertise the correct file type for the downloaded file.
3. Implementing an Axios handler to trigger a FileDownload dialog within the browser
Diese Schritte sind größtenteils machbar - werden jedoch durch die Beziehung des Browsers zu CORS erheblich erschwert. Ein Schritt auf einmal:
1. Konfigurieren Sie Ihren (HTTP-) Server
Bei Verwendung der Transportsicherheit kann JavaScript, das in einem Browser ausgeführt wird, [beabsichtigt] nur auf 6 der vom HTTP-Server tatsächlich gesendeten HTTP-Header zugreifen. Wenn der Server einen Dateinamen für den Download vorschlagen soll, müssen wir den Browser darüber informieren, dass JavaScript "OK" ist, um Zugriff auf andere Header zu erhalten, in denen der vorgeschlagene Dateiname transportiert wird.
Nehmen wir zur Diskussion an, dass der Server den vorgeschlagenen Dateinamen in einem HTTP-Header namens X-Suggested-Filename übertragen soll . Der HTTP-Server teilt dem Browser mit, dass es in Ordnung ist , diesen empfangenen benutzerdefinierten Header für JavaScript / Axios mit dem folgenden Header verfügbar zu machen:
Access-Control-Expose-Headers: X-Suggested-Filename
Die genaue Konfiguration Ihres HTTP-Servers zum Festlegen dieses Headers variiert von Produkt zu Produkt.
Eine vollständige Erläuterung und detaillierte Beschreibung dieser Standardheader finden Sie unter https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers .
2. Implementieren Sie den serverseitigen Dienst
Ihre serverseitige Service-Implementierung muss jetzt zwei Dinge ausführen:
1. Create the (binary) document and assign correct ContentType to the response
2. Assign the custom header (X-Suggested-Filename) containing the suggested file name for the client
Dies erfolgt je nach gewähltem Technologie-Stack auf unterschiedliche Weise. Ich werde ein Beispiel mit dem JavaEE 7-Standard skizzieren, das einen Excel-Bericht ausgeben soll:
@GET
@Path("/report/excel")
@Produces("application/vnd.ms-excel")
public Response getAllergyAndPreferencesReport() {
// Create the document which should be downloaded
final byte[] theDocumentData = ....
// Define a suggested filename
final String filename = ...
// Create the JAXRS response
// Don't forget to include the filename in 2 HTTP headers:
//
// a) The standard 'Content-Disposition' one, and
// b) The custom 'X-Suggested-Filename'
//
final Response.ResponseBuilder builder = Response.ok(
theDocumentData, "application/vnd.ms-excel")
.header("X-Suggested-Filename", fileName);
builder.header("Content-Disposition", "attachment; filename=" + fileName);
// All Done.
return builder.build();
}
Der Dienst gibt jetzt das Binärdokument aus (in diesem Fall einen Excel-Bericht), legt den richtigen Inhaltstyp fest und sendet außerdem einen benutzerdefinierten HTTP-Header mit dem vorgeschlagenen Dateinamen, der beim Speichern des Dokuments verwendet werden soll.
3. Implementieren Sie einen Axios-Handler für das empfangene Dokument
Hier gibt es einige Fallstricke. Stellen Sie daher sicher, dass alle Details korrekt konfiguriert sind:
- Der Dienst antwortet auf @GET (dh HTTP GET), daher muss der Axios-Aufruf 'axios.get (...)' sein.
- Das Dokument wird als Bytestrom übertragen. Sie müssen axios daher anweisen, die Antwort als HTML5-Blob zu behandeln. (Dh Antworttyp: 'Blob' ).
- In diesem Fall wird die JavaScript-Bibliothek zum Speichern von Dateien verwendet, um das Browserdialogfeld zu öffnen. Sie könnten jedoch eine andere wählen.
Die Axios-Implementierung des Skeletts wäre dann wie folgt:
// Fetch the dynamically generated excel document from the server.
axios.get(resource, {responseType: 'blob'}).then((response) => {
// Log somewhat to show that the browser actually exposes the custom HTTP header
const fileNameHeader = "x-suggested-filename";
const suggestedFileName = response.headers[fileNameHeader];'
const effectiveFileName = (suggestedFileName === undefined
? "allergierOchPreferenser.xls"
: suggestedFileName);
console.log("Received header [" + fileNameHeader + "]: " + suggestedFileName
+ ", effective fileName: " + effectiveFileName);
// Let the user save the file.
FileSaver.saveAs(response.data, effectiveFileName);
}).catch((response) => {
console.error("Could not Download the Excel report from the backend.", response);
});