Seite 1 von 1

Konvertierungsfehler

Verfasst: Donnerstag 1. Juli 2010, 17:55
von rads
Hallo zusammen,

ich habe ein kleines Prbolem mit Umlauten und Sonderzeichen:

Beispiel: stören könnte

Umfeld und Vorgehen:

Ich generiere mit Genshi ein HTML Dokument zusammen (hier stimmts noch)
Anschließend versende ich über httplib.HTTPConnection das ganze an ein Java Servlet (HTTP Post).
Das Javaservlet sendet das ganze in (noch) unveränderter form mittels einen Post-Response
als Content wieder zurück.

Anschließend gebe ich das ganze an den Benutzer zurück und zeige es im Browser an (Umweg saveAs)

Code: Alles auswählen

if fileName and fileExtension:
            req.send_header('Content-Disposition', 'filename=%s.%s' % 
                        (fileName, fileExtension))
        req.end_headers()
        req.write(fileContent)
Aber ok, wahrscheinlich ist es eine einfach Umwandlung, welche vor dem Versenden machen muss?
Ich habe es mit

Code: Alles auswählen

 #file ist ein Stream Object
file = str(file).encode('utf-8')
versucht, wahrscheinlich bring ich auch bei den Formaten etwas durcheinander.

Wie könnte ich das eventuell lösen?

Danke schonmal

Grüße

Stefan

Re: Konvertierungsfehler

Verfasst: Donnerstag 1. Juli 2010, 18:59
von Hyperion

Re: Konvertierungsfehler

Verfasst: Donnerstag 1. Juli 2010, 20:15
von cofi

Code: Alles auswählen

 #file ist ein Stream Object
file = str(file).encode('utf-8')
`str` gibt einen Byte-String zurueck, und `encode` kodiert in einen Byte-String, darum ist `encode` v.a. bei `unicode` Objekten nuetzlich, so ist der Inhalt doppelt kodiert.

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 11:29
von rads
Hallo,

danke für die Antworten.

Das versenden mittels Post funktioniert jetzt ganz gut.
Allerdings habe ich jetzt ein ähnliches Problem

Ich sende von Java ein ODF-File als Post-Response im HTTP.Body zurück an Python (Datenquelle ByteArrayStream)
Die Daten kommen auch vollständig an, allerdings wenn ich die daten mittels Get - Response an den Benutzer zurück
sende wird das ODF File ungültig (auf der Java seite ist es gültig da ich es extra zwischgengespeichert habe, um dort
den Fehler auszuschließen)

An sich die Zwei Methoden

Der Post (nur zu vollständigkeit halber)

Code: Alles auswählen

def httpPost(self,server,port,address,file,template,arguments):

            headers = {"Content-type": "text/html",
                        "Accept": "text/html",
                        "Template":str(template),
                        "Arguments":str(arguments)}

            conn = httplib.HTTPConnection(str(server),str(port),timeout=10000)

            conn.request("POST", str(address), str(file),headers)
            
            responseStatus ="500"
            responseReason = "Internal Server Error"
            try:
                response = conn.getresponse()
                responseStatus = response.status
                responseReason = response.reason
                data = response.read()
            except Exception, e:
                print e
            conn.close()
            return data,responseStatus,responseReason


Get-Versenden (File an den Benutzer senden)

Code: Alles auswählen

def sendOdfFile(self,fileName,fileExtension, fileContent,req,responseStatus,responseReason):
        print type(fileContent)
#        if isinstance(fileContent, unicode): #unicode
#                fileContent = fileContent.encode('utf8')
        print fileContent
        req.send_response("%s %s"%(responseStatus,responseReason))
        req.send_header('Content-Type', '"Content-type": "application/x-www-form-urlencoded"')
        req.send_header('Content-Length', len(fileContent))
        if fileName and fileExtension:
            req.send_header('Content-Disposition', 'filename=%s.%s' % 
                        (fileName, fileExtension))
        req.end_headers()
        req.write(fileContent)
        raise RequestDone
Ausgabe des Files in der Console "sieht eigentlich korrekt aus"
Bild

Ich denke das Problem ist, dass das Ergebnis des Post-Response ein String ist (type(fileContent)) = str,
wahrscheinlich müsste ich das dort in bytes umwandeln?

Oder mach ich einfach nur einen Fehler bei den HTTP Headers?

Danke schonmal

Grüße

Stefan

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 12:13
von BlackJack
@rads: Wie stellst Du das "ungültig" denn fest? Ist da irgendwo Windows involviert und Du hast vielleicht vergessen bei `open()` anzugeben, dass es sich um eine Binärdatei handelt?

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 13:24
von rads
Hi und schonmal danke für die Antwort

Ich sende das File ja mit dem Get Request mit und bekomme dann im Browser ein Dialog "Speichern unter"
Anschließend speichere ich das z.b. unter C: ab.
Die gespeicherte Dateigröße stimmt aufs byte mit der ursprungsgröße überein, allerdings meldet Openoffice
das dieses File ungültig ist und repariert werden muss, was natürlich fehl schlägt. Komplett kaputt ist
das file auch nicht, ich kann das file als zip öffnen, auch sind dort nur style.xml und content.xml ungültig,
soweit ich das gesehen habe. Aber wie gesagt, das file ist gültig auf der Serverseite erstellt.

Auf der Javaecke bekomme ich ein HTML File zugesendet (welches ich mit openoffice dann zu einem odf umwandelt)
Hier muss ich auch schon mit

Code: Alles auswählen

String contentConverted = new String(content.toString().getBytes(), UTF_8);
wandeln

Habe das ganze auch im Pyton versucht, allerdins ohne erfolg.
rads hat geschrieben:# if isinstance(fileContent, unicode): #unicode
# fileContent = fileContent.encode('utf8')
Ich wollte ein paar content-types durchprobieren, vielleicht liegt es daran, obwohl ich dachte das es sich
hierbei nur um eine notiz handelt.

Grüße

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 13:56
von rads
Nur noch zum Beweis:

ich speichere testweise die gleichen Daten beim server
Datenquelle: odfContent (ByteArrayOutputStream)
Versende das über einen PrintWriter (unterstützt nur String) mit response.getWriter().println(odfContent)

CodeAuszug

Code: Alles auswählen

ByteArrayOutputStream odfContent;

			odfContent = convertContent(currentFilePath, getTemplateFolder(
					currentFilePath, template), getSoureFolder(currentFilePath,
					session.getId()), request.getHeader(ARGUMENTS));
			// Response
PrintWriter out = response.getWriter();
			
                        #Test zum speichern der Datei #####
			FileOutputStream file = new FileOutputStream(new File("c:/testistest.odf"));
			file.write(odfContent.toByteArray());
			file.flush();
			file.close();
                        #########################			
			
			response.setStatus(response.SC_OK);
out.println(odfContent);
			out.close();

Kann bei der seite maximal am PrintWriter und der Methode println liegen, oder ich brauche hier zwangsläufig einen Content-Type im html header?

Print methode kann es nach Api eigentlich nicht sein:

Code: Alles auswählen

public void print(Object obj)
Prints an object. The string produced by the String.valueOf(Object) method is translated into bytes according to the platform's default character encoding, and these bytes are written in exactly the manner of the write(int) method. 
Hab auch out.write(odfContent.toString()); ausprobiert, aber wie api schon vermuten lässt, keine Änderung.

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 14:46
von Hyperion
rads hat geschrieben: Ich sende das File ja mit dem Get Request mit und bekomme dann im Browser ein Dialog "Speichern unter"
Anschließend speichere ich das z.b. unter C: ab.
Die gespeicherte Dateigröße stimmt aufs byte mit der ursprungsgröße überein, allerdings meldet Openoffice
das dieses File ungültig ist und repariert werden muss, was natürlich fehl schlägt.
Interessant wäre hier zusätzlich, wie es mit dem md5-Wert aussieht! Sind die Dateien exakt gleich, so ist bereits vorher etwas dummes passiert. Wenn Du tatsächlich nur Bytes überträgst, dann sollte da eigentlich nichts schief laufen.

Imho deutet da eh schon viel darauf hin, wenn man die Datei anstandslos als Zip-File entpacken kann...

Also: Wo wir die Datei "manipuliert"? Da muss ja irgend etwas vor dem Senden passieren. Sollte die Datei unmittelbar vor dem Senden (und nach der Manipulation) identisch sein mit der Datei, die schließlich übertragen wurde, dann muss der Fehler zuvor passieren.

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 14:57
von rads
Der Fehler liegt definitiv zwischen dem HTTP Post Response auf Java-Seite und deren Verarbeitung auf Python Seite.

Wie gezeigt, ich speichere
- auf Java seite unmittelbar vor dem senden das File lokal ab, und dort ist es gültig

... versenden ...
- auf der Python seite erhalte ich mittels response.read() die gleiche Anzahl der Bytes. Diese speichere ich zu
testzwecken wie folgt ab (also auch wieder direkt unmittelbar)

Code: Alles auswählen

          
                fobj = open("c:/test.odt", "wb") 
                fobj.write(data)
                fobj.close()
als ergebniss von data = response.read() hat zur Folge das data ein 'str' ist (wie oben gezeigt)

Muss quasi ein Fehler beim http post response sein, hat der content-data attributswert (z.b. application/zip)
http://de.selfhtml.org/navigation/suche ... =mime+type

Wie gesagt, die Javaseite versendet einen Bytestring und ist sonst absolut fehlerfrei, da sonst der test mit dem speichern der datei vor dem submit nicht funktionieren würde.


Grüße

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 15:00
von Hyperion
Was ist denn nun mit dem md5-Wert? Gleiche den doch einmal ab!

Ist zip denn wirklich so tollerant? Ich kann mir nicht vorstellen, dass das Archiv noch gültig wäre, wenn durch den Transport Bytes geändert würden... aber auch da hilft md5 ;-)

Was passiert bei anderen Dokumenten? Hast Du es mal mit einer anderen Office-Datei probiert?

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 15:04
von rads
Nochmal zum Workflow:
Python erstellt eine html datei (W3C gültig) und sendet es an ein Java Servlet. HTTP Post Request

Das Java Servlet verarbeitet dies mit OpenOffice und gibt ein ODF Dokument über den HTTP Post Response zurück.
>>Fehler<<
Python (server) gibt file an client weiter (HTTP Get Request/Response, noch uninteressant, da davor der fehler)

Ich werd das mit md5 passieren, direkt aus den Bytestream ist ja wohl nicht?

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 15:17
von rads
Bild

Bild

Anbei die gewünschten md5 checksum.
Und bisl screenshots.

Aber das was nicht stimmt wissen wir ja, interessanter wäre ja woran es liegt :)
Die Dateiinformationen weichen ab, da ich auf der javaseite eine odf datei kopiere (und somit als vorlage verwende)
und in dieser dann den kontent einfüge. Nach dem Versenden und speichern des pyhton str in eine zwangsläufig neu
datei hat wohl einen verlust dieser informatinen zur folge, vielleicht wird auch so die datei ungültig?

Na schaun wir mal und suchen weiter.

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 15:24
von Hyperion
Noch mal zur Sicherheit:

Kann man das ODF-Dokument nach Erstellung durch das Servlet mit OO.org öffnen?
Kann man das Dokument nach der Übertragung an den Python-Server unzippen ohne Fehlermeldung?

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 15:56
von rads
Java- Serverseite: Datei speichern, OOo öffnen möglich und Unzip möglich
Python- Serverseite: OOo nicht möglich Unzip nicht möglich (öffnen/browsen mit Zipprogramm 7zip schon möglich)

Bild

Als Mime Type verwende ich den gleichen wie im OOo dokument standardmässig angegeben: application/vnd.oasis.opendocument.text
Habe hier aber auch schon viele andere verwendet.

Anmerkung: Die Meldung zum Kompressionsverfahren. die xml datei ist im original sowie immer leer, wahrscheinlich deswegen die Meldung.

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 16:54
von rads
So, keine Ahnung ob das schön ist

aber ich codiere jetzt auf der Javaseite mittels BASE64Encoder()
und auf Python Seite mit base64.b64decode.

Funktioniert wunderbar, hat das für mich irgendwelche Risiken?
(Geschwindigkeit/Datenvolumen ist vernachlässigbar, da könnte man bei dem Reportgenerartor
eher ansetzten)

Grüße Stefan

Re: Konvertierungsfehler

Verfasst: Donnerstag 8. Juli 2010, 17:32
von BlackJack
@rads: Bei dem Code hier:

Code: Alles auswählen

String contentConverted = new String(content.toString().getBytes(), UTF_8);
Was hat `content` für einen Typ? Und ist Dir klar das `getBytes()` ohne Argument problematisch ist, weil es vom System abhängt welche Kodierung da verwendet wird. Wenn das nicht mit der tatsächlichen Kodierung der Daten übereinstimmt, gibt's an der Stelle Probleme.

Ich denke Dein Problem hat was damit zu tun, dass Du versuchst Binärdaten auf der Java-Seite als `String`\s zu behandeln. Das geht nicht. `String` in Java entspricht `unicode` in Python. Darin haben Binärdaten nichts zu suchen. Das gleiche gilt für den `PrintWriter`. Wenn der nur `String` versenden kann, muss man die Binärdaten als Zeichenkette kodieren. Base64 ist eine Möglichkeit dafür.

Re: Konvertierungsfehler

Verfasst: Freitag 9. Juli 2010, 11:00
von rads
BlackJack hat geschrieben:Was hat `content` für einen Typ?

Code: Alles auswählen

// request ^= HttpServletRequest
//getReader liefert einen BufferedReader
BufferedReader reader = request.getReader();
//Stringbuilder zum zeilenweise einlesen des Inhaltes
StringBuilder content = new StringBuilder();
BlackJack hat geschrieben:Ich denke Dein Problem hat was damit zu tun,
BlackJack hat geschrieben:Dir klar das `getBytes()` ohne Argument problematisch ist,
Nein genau das war mir nicht klar, hatte zwar schon einige verteilte Anwendungen
auf unterschiedlichen Systemem/Betreibssystemen/Architekturen und bis jetzt
kein Problem. Aber danke für den Hinweis, wenn das offenbar zu Fehlern führen kann
dann wird es vielleicht daran liegen.

Vielen Dank Blackjack, wie immer ein Beereicherung für mich :)
BlackJack hat geschrieben:Base64 ist eine Möglichkeit dafür.
Mach ich, nicht ideal aber immerhin eine funktionierende und hoffetlich robuste Lösung.