Inputstream in file schreiben?

Diskutiere Inputstream in file schreiben? im Java Basics - Anfänger-Themen Bereich.
B

beta20

Hallo,

ich hänge gerade beim Reinschreiben eines Inputstream ins eine Datei.

Ich lasse mir einen InputStream genieren:

-> Ich geniere mir einen InputStream (PDF, welches später per Email in meinen Anhang versendet werden soll)
Java:
InputStream is = pdfDocumentGenerationService.createPdfWithAttachments(offer.getDocumentDesigner(),fileName, false);
Diesen Inputstream möchte ich nun wiederum physikalisch in eine Datei bei mir auf dem Rechner schreiben:

Hier verwende ich dann:
Java:
File destFile = new File("mypath.pdf");
FileUtils.copyInputStreamToFile(inputStream, destFile);
Prinzipiell wird das File erzeugt, aber die PDF hat 0kb, also sprich es fehlt der Content.

Was mache ich falsch?

Danke für jede Hilfe
 
B

BestGoalkeeper

Nochmal der Hint, dass du in einen InputStream nur schreiben kannst. ;)

Ungeachtet dessen, muss der Stream natürlich auch geschlossen werden...
 
T

temi

Nochmal der Hint, dass du in einen InputStream nur schreiben kannst. ;)

Ungeachtet dessen, muss der Stream natürlich auch geschlossen werden...
Ich nehme an, es handelt sich um ApacheCommons FileUtils?
public static void copyInputStreamToFile(InputStream source, File destination)

Copies bytes from an InputStream source to a file destination. The directories up to destination will be created if they don't already exist. destination will be overwritten if it already exists. The source stream is closed.
 
mrBrown

mrBrown

Nochmal der Hint, dass du in einen InputStream nur schreiben kannst. ;)
Andersrum. Aus einem InputStream kann man lesen, in einen OutputStream schreiben.

Ungeachtet dessen, muss der Stream natürlich auch geschlossen werden...
Das macht FileUtils.copyInputStreamToFile.


-> Ich geniere mir einen InputStream (PDF, welches später per Email in meinen Anhang versendet werden soll)
Enthält der InputStream denn wirklich auch Daten?
 
B

BestGoalkeeper

Die zwei Snippets sehen auf den ersten Blick korrekt aus.

Kann mir aber nicht herleiten, wofür "false" steht...
 
B

beta20

Java:
pdfDocumentGenerationService.createPdfWithAttachments(offer.getDocumentDesigner(),fileName, false)
Dieser Code generiert mir ein Inputstream aus einer vorhandenen Webseite (siehe auch in einem anderen Beitrag von mir hier).
Das funktioniert auch und ich übergebe den Inputstream einem anderen Objekt, welcher dann mir eine Email versendet.
Im Anhang der Email befindet sich dann die PDF, daher würde ich sagen, dass das passt und der Stream auch Daten enthält....

Ich bin nun verwirrt...
Das heißt ich muss den InputStream in einen Outputstream wandeln und dann in die Datei (File) schreiben?
 
mrBrown

mrBrown

Das heißt ich muss den InputStream in einen Outputstream wandeln und dann in die Datei (File) schreiben?
Nein.

Dieser Code generiert mir ein Inputstream aus einer vorhandenen Webseite (siehe auch in einem anderen Beitrag von mir hier).
Das funktioniert auch und ich übergebe den Inputstream einem anderen Objekt, welcher dann mir eine Email versendet.
Im Anhang der Email befindet sich dann die PDF, daher würde ich sagen, dass das passt und der Stream auch Daten enthält....
Im anderem Forums-Thread hast du mehrere Threads genutzt, zb mit ExecutorService genutzt, hast du sichergestellt dass das keine Probleme verursacht?

Ansonsten UnitTests für die einzelnen Teile schreiben, damit kann man den Fehler sicher eingrenzen.

Möglich wäre auch mit TeeInputStream und ByteArrayOutputStream zu loggen, was geschrieben wird.
 
B

beta20

Ich habe es mal im Debug Modus ausgeführt.

Es scheint, dass während dem Senden bzw. dem Anhang hinzufügen der Fehler auftritt, sodass die PDF nicht richtig generiert wird.

Dieser Code wird beim Senden ausgeführt, sodass der Anhang erstellt wird.

Java:
    private Multipart addAttachments(Multipart multipart, EmailHelperClass email)
            throws MessagingException, IOException {
....
        if (attachments != null && attachments.size() > 0) {
            for (EmailAttachment attachment : attachments) {
       ...
                if (attachment.getInputStream() != null) {
                    byte[] bytes = IOUtils.toByteArray(attachment.getInputStream());
                    source = new ByteArrayDataSource(bytes, attachment.getMimeType());
                } 
            }
        }

        return multipart;
    }
Das Problem ist hier:
byte[] bytes = IOUtils.toByteArray(attachment.getInputStream());
source = new ByteArrayDataSource(bytes, attachment.getMimeType());



Nun meine Frage:
a) was passiert in dem Code, dass das PDF nicht richtig generiert wird?
b) Wie muss mein Code angepasst werden (ohne unbedingt eine Änderung in Multipart addAttachments vornehmen zu müssen?
 
Zuletzt bearbeitet:
B

beta20

1)
InputStream is = pdfDocumentGenerationService.createPdfWithAttachments(offer.getDocumentDesigner(),
fileName, false);
-> Hier verwende ich ExecutorService

2) Code in post #12
-> Sprich der Inputstream wird in ein Objekt (EmailAttachment) hingeschrieben und dann wird die Email versendet (inkl. Anhang, also der Inputstream)

3) Erstellung des Files (Physikalisch)
File destFile = new File("mypath.pdf");
FileUtils.copyInputStreamToFile(inputStream, destFile);

Wie kann ich das denn lösen?
Kann ich nochmals eine Kopie von InputStream is machen, welchen ich dann in 3) verwende?

Ich bekomme auch keinen Compiler Fehler, das File ist einfach nicht korrekt gefüllt.
 
mrBrown

mrBrown

Wie kann ich das denn lösen?
Kann ich nochmals eine Kopie von InputStream is machen, welchen ich dann in 3) verwende?
Ja, oder aber mal das ganze Design überdenken. InputStreams scheinen nicht die sinnvollste Wahl zu sein, wenn du mehrmals daraus lesen musst.

Ich bekomme auch keinen Compiler Fehler, das File ist einfach nicht korrekt gefüllt.
Einen Laufzeit-Fehler würdest du bekommen, wenn du Streams korrekt schließt.
 
J

JustNobody

Also ich sehe zwei Möglichkeiten:
a) Schreib die Daten erst in die Datei - dann kannst Du die Datei wieder lesen.

b) Oder speichere die Daten zwischen um diese dann von dem Zwischenspeicher aus zu nutzen.

b dürfte einfacher sein, denn Du liest ja alles schon in ein byte Array. Also Du kannst das byte Array ja erneut nutzen für einen Stream:
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
und dann diesen InputStream nutzen für das schreiben in die Datei.

A hat den Vorteil, dass Du es nicht im Speicher halten musst aber dafür hast du mehr IO zur Platte (Da dort aber auch ein Cache aktiv sein sollte, sollte das ggf. auch nicht ins Gewicht fallen). B hast Du aber schon fast fertig ...
 
T

temi

Vielleicht kann man was mit Stream#mark() und Stream#reset() machen? Das ist aber einfach wild ins Blaue geraten und würde mir auch nicht sehr sauber vorkommen.
 
B

beta20

Wie kann ich diese Zeile umschreiben, dass der InputStream nicht geschlossen wird (was die Funktion wohl macht):
FileUtils.copyInputStreamToFile(inputStream, destFile);
 
Thema: 

Inputstream in file schreiben?

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben