Meine Infrastruktur:
Firefox <------> WebServlet auf Tomcat <------> Server
Ich verwende kein weiteres Framework, nur die von Tomcat mitgelieferten Jars servlet-api.jar
und jaxws-api-2.3.0.jar
.
Mein Problem:
Ich versuche eine serverseitig erzeugte Exceldatei im .xlsx-Format, welche sich direkt auf dem Server auch problemlos öffnen lässt, über mein im Tomcat laufendes WebServlet im Browser herunterzuladen. Mit Textdateien klappt das bisher ganz problemlos, mit .xlsx-Dateien leider nicht, Excel mag die heruntergeladenen Dateien einfach nicht öffnen und sie unterscheiden sich auch inhaltlich, wenn auch nicht in der Größe der Datei.
Zuerst habe ich gedacht, dass es am falschen ContentType liegen könnte und habe diesen auf
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
gesetzt.
Das hat nicht zum Erfolg geführt.
Zusätzlich setze ich in für jeden Download:
response.setHeader("Content-disposition", "attachment; filename=" + downloadFilename);
damit der Browser den Speichern-Dialog öffnet.
Dann habe ich auf dem Server den Dateiinhalt in Base64 kodiert und übertragen:
public String readLocalBinaryFileToBase64FileContent(String filename) {
byte[] bytes = readSmallBinaryFile(filename);
Base64.Encoder encoder = Base64.getEncoder();
byte[] encodedBytes = encoder.encode(bytes);
String base64FileContent = new String(encodedBytes);
return base64FileContent;
}
private byte[] readSmallBinaryFile(String filename) {
try {
Path path = Paths.get(filename);
return Files.readAllBytes(path);
}
catch (IOException exception) {
throw new RuntimeException(exception);
}
}
Und entsprechend im WebServlet diesen wieder dekodiert mit:
public String createBinaryStringFromBase64FileContent(String base64FileContent) {
byte[] encodedBytes = base64FileContent.getBytes();
Base64.Decoder decoder = Base64.getDecoder();
byte[] decodedBytes = decoder.decode(encodedBytes);
String decoded = new String(decodedBytes);
return decoded;
}
Abgesendet wird er im WebServlet wie jeder andere Inhalt (erzeugte HTML-Seite, Text-Dateiinhalt zum Download, …):
private void sendResponse(String payload) {
try {
tryToSendResponse(payload);
}
catch(Exception e) {
throw new HTTPException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
private void tryToSendResponse(String payload) throws IOException {
OutputStream out = response.getOutputStream();
out.write(payload.getBytes());
out.flush();
}
Zuletzt habe ich noch den binären ContentType probiert:
"application/octet-stream"
in der Hoffnung, dass es dann klappt, tut es aber auch nicht.
Für ContentTypes siehe https://wiki.selfhtml.org/wiki/MIME-Type/Übersicht
Hat jemand eine Idee, was ich noch versuchen könnte? Ich habe schon sehr viel
gegoogelt, bin aber gerade mit meinem Latein am Ende.