Sie setzen die Antwortheader nach dem Schreiben des Dateiinhalts in den Ausgabestrom. Dies ist ziemlich spät im Antwortlebenszyklus, um Header zu setzen. Die richtige Reihenfolge der Operationen sollte sein, zuerst die Header zu setzen und dann den Inhalt der Datei in den Ausgabestrom des Servlets zu schreiben.
Daher sollte Ihre Methode wie folgt geschrieben werden (das wird nicht kompilieren, da es nur eine Darstellung ist):
response.setContentType("application/force-download");
response.setContentLength((int)f.length());
//response.setContentLength(-1);
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName);
...
...
File f= new File(fileName);
InputStream in = new FileInputStream(f);
BufferedInputStream bin = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(bin);
while(din.available() > 0){
out.print(din.readLine());
out.print("\n");
}
Der Grund für das Scheitern ist, dass es möglich ist, dass die tatsächlichen Header, die vom Servlet gesendet werden, von dem abweichen, was Sie senden möchten. Immerhin, wenn der Servlet-Container nicht weiß, welche Header (die vor dem Body in der HTTP-Antwort erscheinen) vorhanden sind, kann er geeignete Header setzen, um sicherzustellen, dass die Antwort gültig ist; das Setzen der Header nachdem die Datei geschrieben wurde, ist daher nutzlos und überflüssig, da der Container die Header bereits gesetzt haben könnte. Dies können Sie überprüfen, indem Sie den Netzwerkverkehr mit Wireshark oder einem HTTP-Debugging-Proxy wie Fiddler oder WebScarab betrachten.
Sie können auch die Java EE API-Dokumentation für ServletResponse.setContentType konsultieren, um dieses Verhalten zu verstehen:
Setzt den Inhaltstyp der an den Client gesendeten Antwort, wenn die Antwort noch nicht committed wurde. Der angegebene Inhaltstyp kann eine Zeichenkodierungsspezifikation enthalten, z. B. text/html;charset=UTF-8. Die Zeichenkodierung der Antwort wird nur aus dem angegebenen Inhaltstyp gesetzt, wenn diese Methode aufgerufen wird, bevor getWriter aufgerufen wird.
Diese Methode kann wiederholt aufgerufen werden, um Inhaltstyp und Zeichenkodierung zu ändern. Diese Methode hat keine Wirkung, wenn sie nachdem die Antwort committed wurde, aufgerufen wird.
...