# PDF per Servlet übertragen, danach keinen Inhalt mehr



## ProfSamba (23. Feb 2007)

Hi Leute...

Also ich habe da ein Problem, bei dem Ihr mir hoffentlich helfen könnt...

Ich erzeuge mir per iText ein PDF und lege es in einen Pfad ausserhalb der WebRoot.

Eine Methode liest mir das File wieder als byte[] ein:


```
public static byte[] getPdf(){

        File file = new File("c:/test.pdf");
        
        byte[] data = new byte[(int)file.length()];
        try {
            FileInputStream fis = new FileInputStream(file);
            
            BufferedInputStream buffer = new BufferedInputStream(fis);
            
            buffer.read(data); 
            
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } 
        return data;
    }
```

Mein Servlet schickt das dann an den Client:

```
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        
        byte[] data = PdfReport.getPdf();
        
        response.setContentLength(data.length);
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition","attachment; filename=\"Report.pdf\"");
        response.setHeader("Content-Transfer-Encoding","binary");

        response.getOutputStream().write(data);

    }
```


Das funktioniert alles einwandfrei, nur jetzt kommt das erstaunliche...
Das heruntergeladene PDF kann ich mir zwar ansehen, es enthält jedoch keinen Text...
alle Header Informationen sind im PDF zwar enthalten (z.B. Anzahl der Seiten, Autor, etc) aber der Text wird nicht angezeigt.
die Größe der PDF-Dateien (auf dem Server und auf dem Client) sind absolut identisch...

Ich habe das heruntergeladene PDF auch schon auf mehreren Rechnerngetestet... es liegt also nicht an der Acrobat Version oder so...

Ich dachte erst, dass es am Character-Encoding liegt, aber ich denke, dass das so richtig ist...

Hat von Euch noch jemand eine Idee, woran es liegen könnte?

Danke schonmal und viele Grüße
Matze


----------



## Mersi (25. Feb 2007)

Hi!

Ich weiß zwar nicht, ob ich Dir weiterhelfen kann, aber ich mache das direkt über den Request und nicht mit einer extra Übertragung. [Und ja, das klappt super ;-)]

Also so:

```
response.setContentType("application/pdf");
PdfWriter pdfWriter = PdfWriter.getInstance(document, response.getOutputStream());
```

Vielleicht kannst Du damit das Problem ja umgehen...


----------



## ProfSamba (25. Feb 2007)

Hi Mersi.

Danke für deine Antwort.
Den Umweg gehe ich nur deshalb, weil das Servlet keinen direkten Zugriff auf das Dokument hat. Ich werde mal versuchen, dass ich ein Objekt vom Typ PdfDocument übergebe, anstatt ein Byte-Array, hoffentlich tut das...

Ich werde es morgen mal versuchen und berichten...

Gruß


----------



## ProfSamba (26. Feb 2007)

Tja, also ich wollte das heute nochmal Testen, aber ich habe leider keine Möglichkeit aus einem bereits existierenden PDF ein (iText) Document zu erstellen, dass ich dann weiter geben könnte...

Hat denn jemand anders schonmal ein PDF-Download realisiert?

Ich habe jetzt zum Testen einen direkten Zugriff vom Servlet auf die Datei erstellt, aber auch das bringt keinen Unterschied.

Hier mein aktueller Code:

```
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

        Properties config = ConfigLoader.getConfig();
        File file = new File(config.getProperty("workingdir")+"/Java Web Service.pdf");
        
        byte[] data = new byte[(int)file.length()];

        try {
            
            FileInputStream fis = new FileInputStream(file);
            BufferedInputStream buffy = new BufferedInputStream(fis);
            buffy.read(data); 
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } 
        
        response.setContentLength(data.length);
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition","attachment; filename=\"Java Web Service.pdf\"");
        response.setHeader("Cache-Control","no-cache");
      
        response.getOutputStream().write(data);
    }
```

Noch jemand eine andere Idee, warum das PDF nicht so ankommt, wie ich es auf Serverseite habe?
Mache ich vielleicht schon beim einlesen etwas falsch?


----------



## ProfSamba (26. Feb 2007)

So, nachdem ich jetzt wieder ein bisschen weiter geforscht habe, habe ich festgestellt, dass sich das Datum der Datei beim Download ändert.

Die Original datei z.B. wurde am 11.11.2006 erstellt, nach dem Download über das oben gezeigte Servlet steht das "Erzeugt am" Datum immer auf der Uhrzeit, an dem ich es herutergeladen habe... 

Wie kann ich das Datum beibehalten?


----------



## little_b (27. Feb 2007)

im eile des Gefechts hab ich bei Dir nirgends ein close gesehen.
machst Du den stream irgendwo wieder zu?
koennte das problem mit dem inhalt loesen.

so weit ich weiss ist das Datum zB. lastModified nicht im file,
sondern im dazugehoerigen filesystem gespeichert.
demnach muesstest du das extra uebertragen.

viel glueck


----------



## ProfSamba (27. Feb 2007)

```
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    
        response.reset();
        Properties config = ConfigLoader.getConfig();
        
        
        ServletOutputStream sos = response.getOutputStream();
        
      
        byte data[] = new byte[1024000];
        
        BufferedInputStream bis;
        try
        {
            bis = new BufferedInputStream(new \
                        FileInputStream(config.getProperty("workingdir")\
                        +"/test.pdf"));
            
            int count=0;
            while((count=bis.read(data)) != -1){
                sos.write(data,0,count);
            }
            
            bis.close();
        }
        catch(Exception exception) {
            exception.printStackTrace();
        }
        
        sos.close();
    }
```


Also jetzt mit close() für den ServletOutputStream (sos) und den BufferedInputStream (bis). Leider hat das am Verhalten des PDF nichts geändert...
Die Sache mit dem Datum ist auch egal, ich habe gemerkt, dass das Erstellungsdatum nichts mit diesem Verhalten zu tun hat.

Schreibe ich mein byte[] in ein File anstatt in den ServletOutputStream, wird das PDF 1:1 kopiert und ich kann es mir auch ansehen (mit Inhalt), schicke ich es durch den sos, klappt es nicht.

Ich habe es jetzt auch mit anderen PDFs getestet, die ich nicht erstellt habe. Eines der PDFs verlangt nach einem Passwort, nachdem es durch das Servlet verschickt wurde... (das Original verlangt nicht nach einem Passwort)...

Gibt es sonst noch Ideen, was ich falsch gemacht haben könnte? Kann diese Problem jemand nachvollziehen?

Gruß
Matze


----------



## HaBaLeS (28. Feb 2007)

Ich vermute mal, das du nciht alles schreibst, das fie filesize passt kann u.A. auch daran leigen, dass du die Filesize angegebenhast dun er es auffüllt.


Diesen Code habe ich Produktiv im einsatz, versuch´s mal damit


```
private void sendFileToClient(HttpServletResponse res,
         String pOutputFilename, String pMimeType, String pFileName)
         throws Exception {

      ServletOutputStream stream = null;
      BufferedInputStream fif = null;

      FileInputStream zipInStream = new FileInputStream(pFileName);
      fif = new BufferedInputStream(zipInStream);

      res.setHeader("Content-Disposition", "attachment;filename="
            + pOutputFilename);
      res.setContentType(pMimeType);
      res.setContentLength((int) (new File(pFileName)).length());

      int data = 0;
      stream = res.getOutputStream();
      while ((data = fif.read()) != -1) {
         stream.write(data);
      }
      fif.close();
      stream.close();

   }
```


----------



## ProfSamba (28. Feb 2007)

Hi...

Danke für den Code HaBaLeS. Aber das problem ist genau das gleiche... Ich habe deinen Code 1:1 übernommen.
Wenn ich mir ein txt File schicke funktioniert das alles wunderbar. Nur bei einem PDF nicht.

Hast du mit deinem Code schonmal PDFs heruntergeladen?


Gruß
Matze


----------



## HaBaLeS (28. Feb 2007)

Ich hab damit schon zu ziemlich alles als Download gestreamt, da es ein Teil einer Downloadverwaltung ist. 

Sorry aber dann bin ich mit meinem ferndiagnose Latein am Ende :-(


----------



## ProfSamba (28. Feb 2007)

So, ich werde jetzt mal auf einem anderen AppServer testen, mal sehen, ob es was bringt...
Muss ja nicht immer ICH sein, der die Fehler macht  ???:L


----------



## ProfSamba (1. Mrz 2007)

Hallo...

Naja, wie immer lag das Problem wohl doch an mir.   

Ich habe das Servlet nicht direkt aufgerufen, sondern über JSF.

List.jsp

```
<h:commandLink action="showpdf" value="Download"/>
```

faces-config.xml

```
<navigation-case>
            <from-outcome>showpdf</from-outcome>
            <to-view-id>/pdfServlet</to-view-id>
</navigation-case>
```


Wenn ich das so gemacht habe, hat er mir das Pdf "zerschossen", warum weiß ich allerdings nicht...

Jetzt habe ich das ganze so gelöst, dass ich aus der List.jsp nicht mehr den Umweg über die faces-config.xml gehe:

List.jsp

```
<h:outputLink value="../../PdfServlet?id=#{pdf.id}">Anzeigen</h:outputLink>
```

Seitdem funktioniert das Anzeigen des PDF.


Trotzdem habe ich noch eine kleine Frage.
Ist es vielleicht möglich ein Pdf dann über eine ManagedBean zu versenden? Und das Servlet ganz weg zu lassen?

Gruß
Matze


----------



## Gast (8. Mrz 2007)

Hi! Also ich nutze Struts, und musste das auch realisieren, und dort geht es, auch wenn ich es in eine Action packe und mit viewPdf.do anspreche...

Mein Code:


```
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
	HttpServletResponse response) throws Exception {
	String fileName = "test.pdf";
	String fullPath = "C:\\Programme\\JBoss\\server\\default";
	FileInputStream fis = null;
	BufferedOutputStream bos = null;

	try {
		ServletOutputStream out = response.getOutputStream();
		response.setContentType("application/pdf");
		String fileWithFullPath = fullPath + "\\" + fileName;
		System.out.println(fileWithFullPath);
		fis = new FileInputStream(fileWithFullPath);
		bos = new BufferedOutputStream(out);
		byte[] buff = new byte[2048];
		int bytesRead;
		while (-1 != (bytesRead = fis.read(buff, 0, buff.length))) {
			bos.write(buff, 0, bytesRead);
		}
	} catch (IOException e) {
		System.out.println("IO Exception für File: " + fileName);
		e.printStackTrace();
	} finally {
		try {
			if (fis != null)
				fis.close();
			if (bos != null)
				bos.close();
		} catch (IOException e) {
			System.out.println("Error while closing Stream.");
			e.printStackTrace();
		}
	}
	return null;
}
```


----------

