Readfile + Header + RTF

Alles, was PHP betrifft, kann hier besprochen werden.

Readfile + Header + RTF

Postby Leeloo5E » 25. February 2008 16:21

In meinem Skript baue ich mir ein RTF-Dokument und speichere es auf dem Webserver. Per Header und Readfile soll es dem Nutzer zum Download bzw. Ansicht angeboten werden. Das passiert wie folgt:

Code: Select all
 header('Content-type: application/rtf');
 header("Cache-Control: no-cache, must-revalidate");
 header("Content-Length: " . filesize($file));
 header('Content-Disposition: attachment; filename=file.rtf');
                        
 readfile($file);


Es kommt der Downloadaufforderung von FF. Anstatt jedoch zu speichern, möchte ich das Dokument sofort in Augenschein nehmen und lasse mir Microsoft Word öffnen. Allerdings kommt nich die vermutete Ansicht, sondern der pure RTF-Code. Auch beim lokalen Speichern der Datei geht etwas schief, denn auch hier wird nur der RTF-Code angezeigt.

Nur das direkte Aufrufen der Datei vom Server bringt die gewünschte und interpretierte RTF-Anzeige.

Ich vermute, dass es entweder daran liegt, dass ich noch nicht die korrekte Einstellung in PHP gefunden habe oder aber es liegt an den Einstellungen in der php.ini, die noch angepasst werden müssen.
Um ein korrektes PDF zu bekommen, musste ich beispielsweise output_buffering auf 4096 setzen. Gibt es einen weiteren Wert, der die Ausgabe von RTFs beeinflusst und den ich einstellen kann?
Das PDF wird nun korrekt mit den selben obigen Einstellungen zum Download angeboten und die Anzeige ist ebenfalls ok.

Gruß,
Leeloo
Leeloo5E
 
Posts: 37
Joined: 16. April 2006 16:55

Postby Wiedmann » 25. February 2008 16:52

Um ein korrektes PDF zu bekommen, musste ich beispielsweise output_buffering auf 4096 setzen.

Dann hast du aber schon ein anderes Codeproblem, wenn du mit Outputbufferimg arbeiten musst. Grundsätzlich ist das auch für PDF nicht nötig.

Nur das direkte Aufrufen der Datei vom Server bringt die gewünschte und interpretierte RTF-Anzeige.
...
Auch beim lokalen Speichern der Datei geht etwas schief, denn auch hier wird nur der RTF-Code angezeigt.

Wie unterschiedet sich denn diese Datei (über das PHP-Script) genau von der Datei, die du über den direkten Download gespeichert hast. (filecompare)

(BTW: würde es den ohne deinen Cache-Header tun?)
Wiedmann
AF Moderator
 
Posts: 17106
Joined: 01. February 2004 12:38
Location: Stuttgart / Germany

Postby Leeloo5E » 26. February 2008 09:19

Auch wenn ich die Sachen weglasse
Code: Select all
 header("Cache-Control: no-cache, must-revalidate");
 header("Content-Length: " . filesize($file));

kommt das File immer noch kaputt an.

Das FileCompare meldet: Data Missmatch. Was für eine Erkenntnis.

Wieso soll an meinem Code was falsch sein? Die Datei wird ja korrekt auf dem Webserver gespeichert und nur mit den obigen Befehlen aufgerufen. Dabei ist es egal in welchem Browser. Sogar mit Safari kommt nichts Gutes rüber.

Durch die Angabe von output_buffering in der php.ini konnte ich wenigstens das PDF retten, welches zuvor nämlich auch nur in seinem Quelltext und nicht gerendert angezeigt wurde. Da nämlich das Plugin nicht angesprochen wurde. Beim RTF wird der Download erzwungen. Man kann es also runterladen oder ebenso gleich separat in Word öffnen. Nur beide Male ist die Datei kaputt. Word verlangt die Angabe einer Zeichenkodierung und gibt UTF-8 vor. Hilft aber auch nix.

Gruß,
Leeloo
Leeloo5E
 
Posts: 37
Joined: 16. April 2006 16:55

Postby Scory » 26. February 2008 11:35

Kann es sein, dass Du den Output compressed (gzip o.ä.) an den Browser sendest und der dort nicht dekomprimiert wird?
Scory
 

Postby Wiedmann » 26. February 2008 11:50

Das FileCompare meldet: Data Missmatch. Was für eine Erkenntnis.

Sorry, hätte evtl. sagen sollen, dass es hier mehr um eine "optische" Inspektion geht. Also ob die Dateien wirklich total unterschiedlich sind, oder eine "nur" kürzer. Und das was da ist, genau übereinstimmt.

Du könntest es dann mal damit probieren:
http://www.apachefriends.org/de/faq-xam ... netlimiter
Wiedmann
AF Moderator
 
Posts: 17106
Joined: 01. February 2004 12:38
Location: Stuttgart / Germany

Dateiübertragung mit PHP über XAMPP

Postby Leeloo5E » 26. February 2008 13:37

Netdelimiter ist hier nicht installiert. Ich hab auch den ersten Tipp befolgt. In meinem Fall das Auskommentieren von
Code: Select all
#EnableSendfile off
#EnableMMAP off

Bringt nüscht!

Weitere Nachforschungen ergaben, dass
Code: Select all
application/rtf   rtf
appliation/zip    zip

in der mime.types vorhanden sind.

Ebenso tauchen Einträge für rtf und zip in der Datei magic auf.
Allerdings blick ich da bei den ZIP-Einträgen nicht ganz durch.

Code: Select all
# compress:  file(1) magic for pure-compression formats (no archives)
#
# compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, whap, etc.
#
# Formats for various forms of compressed data
# Formats for "compress" proper have been moved into "compress.c",
# because it tries to uncompress it to figure out what's inside.

# standard unix compress
0   string      \037\235   application/octet-stream   x-compress

# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver)
0       string          \037\213        application/octet-stream   x-gzip

# According to gzip.h, this is the correct byte order for packed data.
0   string      \037\036   application/octet-stream
#
# This magic number is byte-order-independent.
#
0   short      017437      application/octet-stream

# XXX - why *two* entries for "compacted data", one of which is
# byte-order independent, and one of which is byte-order dependent?
#
# compacted data
0   short      0x1fff      application/octet-stream
0   string      \377\037   application/octet-stream
# huf output
0   short      0145405      application/octet-stream

# Squeeze and Crunch...
# These numbers were gleaned from the Unix versions of the programs to
# handle these formats.  Note that I can only uncrunch, not crunch, and
# I didn't have a crunched file handy, so the crunch number is untested.
#            Keith Waclena <keith@cerberus.uchicago.edu>
#0   leshort      0x76FF      squeezed data (CP/M, DOS)
#0   leshort      0x76FE      crunched data (CP/M, DOS)

# Freeze
#0   string      \037\237   Frozen file 2.1
#0   string      \037\236   Frozen file 1.0 (or gzip 0.5)

# lzh?
#0   string      \037\240   LZH compressed data

Für RTF siehts schon etwas besser aus:
Code: Select all
# RTF - Rich Text Format
0   string      {\\rtf      application/rtf

Obwohl ein RTF eigentlich mit {\rtf beginnt ...

Und da sind wir schon beim nächsten Problem. Der direkte Vergleich der erzeugten Datei auf dem Webserver und der, die man per Browser herunterläd, zeigen wirklich Unterschiede. Ein RTF kann man ja ganz fein mit einem Editor öffnen. Gesagt getan:
Das fehlerhafte RTF besitzt am Anfang:
Code: Select all
 

Äh, das sollen eigentlich so quadratische Kästche sein. Was auch immer das ist?! Und am Ende fehlt was, was das original hat.
Code: Select all
ge}
\par
}\sect }

Ich vermute mal, dass das was vorne angehängt, hinten abgesägt wird.
Das ganze übrigens so anpassen, dass wenigstens Ende und Anfang übereinstimmen, bringt übrigens gar nix. Word weigert sich weiterhin das RTF korrekt anzuzeigen.

ZIP-technisch gehts ebenfalls immer noch schief. Die Datei wird korrekt erstellt und liegt in den Verzeichnissen des Webservers. Beim Download geht sie aber kaputt. In der php.ini ist nur folgender Wert zu finden, der wohl auf keine Kompression schließen lässt:
Code: Select all
zlib.output_compression = Off


Ich bin immer noch ratlos. Auch die weitere Konfig vom Apachen in XAMPP geben bisher keinen Hinweis ...

Gruß,
Leeloo
Leeloo5E
 
Posts: 37
Joined: 16. April 2006 16:55

Postby Wiedmann » 26. February 2008 13:46

In meinem Fall das Auskommentieren von

Den Apache neu gestartet und Cache im Browser geleert hast du danach schon?

in der mime.types vorhanden sind.

Diese Datei hat mit deinem Problem nichts zu tun.

So grundsätzlich:
Hast du irgendwas in der "httpd.conf" oder "php.ini" geändert (Extensions aktiviert usw.)?


Ansonsten müssten wir uns doch deinem Code zuwenden. (Insbesondere das ganze mal mit einem einfachen Testcode testen)
Wiedmann
AF Moderator
 
Posts: 17106
Joined: 01. February 2004 12:38
Location: Stuttgart / Germany

Postby Leeloo5E » 26. February 2008 14:41

Wiedmann wrote:
In meinem Fall das Auskommentieren von

Den Apache neu gestartet und Cache im Browser geleert hast du danach schon?

Natürlich!
Wiedmann wrote:
in der mime.types vorhanden sind.

Diese Datei hat mit deinem Problem nichts zu tun.

Schade, war aber mal nen Versuch wert, eben dort zu schauen, ob da nicht doch was fehlt, einstellungsmäßig mein ich.


Wiedmann wrote:So grundsätzlich:
Hast du irgendwas in der "httpd.conf" oder "php.ini" geändert (Extensions aktiviert usw.)?


Ansonsten müssten wir uns doch deinem Code zuwenden. (Insbesondere das ganze mal mit einem einfachen Testcode testen)


In der httpd.conf hab ich nüscht gemacht. In der php.ini hab ich nur output_buffering auf 4096 gestellt. Naja ok, vielleicht noch sowas wie log_errors auf On und dann auch den Pfad zur Datei. Aber nichts weltbewegendes.

Der ausschlaggebene Code zur Übergabe der Datei ist folgender:
Code: Select all
 header('Content-type: application/rtf');
 header("Cache-Control: public, must-revalidate");
 header("Content-Length: " . filesize($file));
 header('Content-Disposition: attachment; filename="file.rtf"');
            
 readfile($file);

Ich hab da schon alle möglichen (aus meiner Sicht) Varianten ausprobiert. Für Cache-Control halt mal public, mal no-cache. Das ganze auch mal auskommentiert, genauso wie Content-Length oder sogar den Content-type.

Trail-And-Error:

1. Anzeige RTF-Code in Browser ohne vorangestellt merkwürdige Zeichen oder Abschneiden am Ende mit:
Code: Select all
 readfile($file);


2. Fehlerhaftes RTF zum Download angeboten.
Code: Select all
 header('Content-type: application/rtf');         
 readfile($file);


3. Anzeige korrektes RTF in Browser wie 1.
Code: Select all
 header('Content-Disposition: attachment; filename="file.rtf"');   
 readfile($file);


4. Feherhaftes RTF zum Download angeboten.
Code: Select all
 header('Content-type: application/rtf');
 header('Content-Disposition: attachment; filename="file.rtf"');
 readfile($file);


Die anderen beiden Dinge haben keinen Einfluss. Ob nun no-cache oder public. Beides kann ich auch direkt in der php.ini unter session.cache_limiter angeben. Dort steht übrigens per Default nocache drin.
Problem ist hier wohl folgendes:
Code: Select all
 header('Content-type: application/rtf');

Sobald ich das einschalte, kommt nix korrektes mehr an.

Testweise hab ich jetz einfach mal einen Link auf die fertige Datei gesetzt -> angeklickt und siehe da, sie wird korrekt angezeigt. Kein wunder, weder PHP noch der Apache haben ja jetzt daran rumgefuscht.

Ein weiterere Test bestand darin den obigen Code vollständig in eine eigene Datei zu kopieren und auszuführen. Die merkwürdigen Anfangszeichen traten nun nicht mehr auf. Auch das Ende scheint korrekt zu sein. Word fragt aber immer noch nach der Zeichenkodierung und stellt am Ende auch nur wieder den Code dar anstatt das RTF korrekt zur rendern.

Btw. nutze ich UTF-8 für die HTML-Seiten sowie meinen PHP-Quelltext. Deshalb will der das auch immer so dargestellt haben.

Gruß,
Leeloo

PS: Ich könnte dir ja mal ne korrekte und kaputte Datei zukommen lassen. Das Testfile mit den Header-Funktionen ebenfalls. Wichtig hierbei ist es halt den XAMPP zu verwenden. Denn nur hier tritt das Problem auf. Mein Apache2 unter Suse zickt jedenfalls dabei nicht rum.
Leeloo5E
 
Posts: 37
Joined: 16. April 2006 16:55

Postby Wiedmann » 26. February 2008 15:05

Ein weiterere Test bestand darin den obigen Code vollständig in eine eigene Datei zu kopieren und auszuführen. Die merkwürdigen Anfangszeichen traten nun nicht mehr auf.

Dann scheint wohl doch noch irgendwas in deinem restlichen Code (den wir nicht kennen) , bzw. der restlichen Datei als Ganzes, nicht zu stimmen. Möglicherweise wird dort irgendein Leerzeichen, Zeilenumbruch oder PHP Notice ausgegeben, weshalb du auch mit dem output_buffering pfuschen musst.

Die eigentliche Dateiübertragung (in PHP/Apache) wird nur durch die Funktino readfile() erledigt. Die Header interessieren weder den Apachen noch PHP. Die werden einfach an den Client durchgereicht.

(Tatsächlich kann du ja evtl. in deinem Client sogar überprüfen, ob die Header, wie von dir vorgesehen ,richtig ankommen.)
Wiedmann
AF Moderator
 
Posts: 17106
Joined: 01. February 2004 12:38
Location: Stuttgart / Germany

Postby Scory » 26. February 2008 15:43

Könntest Du irgendwo ein "kaputtes" RTF zum Download anbieten und vielleicht auch im Vergleich dazu das intakte? Das könnte ich mal mit einem Hexeditor auseinandernehmen?

Wie sieht es aus, wenn Du Dein Script auf eine Minimum zusammenstauchst? Ich habe bei mir dieses Script fehlerfrei am Laufen (mit einer kleinen RTF Datei):

Code: Select all
<?php
 $file = "docu.rtf";
 header('Content-type: application/rtf');
 header("Cache-Control: no-cache, must-revalidate");
 header("Content-Length: " . filesize($file));
 header('Content-Disposition: attachment; filename=docu.rtf');
                       
 readfile($file);
?>


Produziert das auch ein fehlerhaftes RTF?
Scory
 

Postby Scory » 26. February 2008 15:53

Wenn ich das alles noch einmal lese - dann weiß ich, was das Problem ist:

Du arbeitest mit Outputbuffering, welches eine Fehlermeldung verhindert, die normalerweise auftauchen würde, wenn die header()-Funktion aufgerufen wird. Da käme todsicher "Headers already sent ... output started at ...".

Und mit einiger Sicherheit ist im Startscript der allererste PHP-Tag nicht in direkt in der ersten Zeile, sondern dort ist (eine oder mehr) Leerzeilen davor. Wenn nicht dort, dann irgendwo in einem includierten Script.

Diese Leerzeilen sind unter MS-DOS die Zeichen CarriageReturn und Newline (\r\n) und unter Unix nur CarriageReturn (\n).

Der Notepad kann UNIX-Textdateien nicht richtig darstellen, weil er die Sequenz \r\n erwartet - wenn stattdessen (bei zwei Leerzeilen beispielsweise) das so aussieht "\n\n", dann "malt" er für jedes Newline-Zeichen ein rechteckiges Kästchen auf dem Bildschirm - genau das, was wir jetzt hier nicht mehr sehen können.

Irgendeines Deiner Scripts sieht also so aus:

Code: Select all


<php
...
...
?>


Und diese beiden Leerzeilen landen ganz am Anfang der RTF-Datei - und machen diese damit kaputt. Weil sie einfach ausgegeben werden, bevor readfile() den Inhalt des RTF-Files hinterher schickt.

Was wetten wir, dass das die Ursache ist?
Scory
 

Postby Leeloo5E » 26. February 2008 15:59

Scheinbar ist das Pfuschen mit output_buffering auch nur im verfuschten XAMPP nötig, denn der normale Apache2 unter Linux akzeptiert den PHP-Quellcode so wie er ist.
Btw.
Code: Select all
error_reporting  =  E_ALL

D.h. auch PHP-Notice müssten angezeigt werden, aber da is nüscht. Und übrigens:
Code: Select all
display_errors = On

Und mein FF zeigt mir als übertragenen Header sowas an:
Code: Select all
HTTP/1.1 200 OK
Tue, 26 Feb 2008 14:42:59 GMT
Apache/2.2.4 (Win32) DAV/2 mod_ssl/2.2.4 OpenSSL/0.9.8d mod_autoindex_color PHP/5.2.1
PHP/5.2.1
no-cache
no-cache,must-revalidate
File Transfer
attachment;filename=file.rtf
utf-8
26735
timeout=5, max=100
Keep-Alive
application/rtf

wobei mir nur der Wert und nicht auch noch der Name in die Zwischenablage kopiert wird.

Ich bezeweifle immer noch seeeeeeehr stark, dass es hier an meinem PHP-Code hakt. Mir hätte das dann nämlich schon sehr viel früher auffallen müssen. Außerdem wäre es nicht das erste Mal, dass mit dem XAMPP etwas nicht funktioniert, was mich dann nämlich auch zurück zum normalen LAMP geführt hat.

@Scory:
ja, auch das verursacht unter XAMPP ein kaputtes RTF.
Versuch doch mal ein heiles RTF per XAMPP runterzuladen. Selbes Problem wie oben beschrieben: RTF wird nicht als RTF dargestellt. Es liegt also nicht an meine Code, sondern an der XAMPP-Konfiguration.

Gruß,
Leeloo

Vielleicht sollte ich noch erwähnen: XAMPP für Windows - derzeitige Testversion 1.6.0a. Problem ebenfalls unter 1.6.4a aufgetreten. Ich teste das jetzt mal in der aktuellen Version 1.6.6a. Hab da aber keine Hoffnung.
Leeloo5E
 
Posts: 37
Joined: 16. April 2006 16:55

gelöst

Postby Leeloo5E » 26. February 2008 16:48

Ok, mein Fehler. Wie kann man auch bloß so blöd sein, sich überhaupt keinen Kopf um die Codierung seiner Dateien zu machen, die den Quellcode beinhalten. Die Auswahl einer UTF-8-Kodierung bewirkt im neuen Xampp 1.6.6 die Fehlermeldung von schon gesendeten Headern und zwar text/html. Hierbei reicht es aus, wenn ein auskommentiertes echo mit HTML-Tags vorher irgendwo steht. Und schon mag mich der Xampp nicht mehr.
Komischerweise kam diese Fehlermeldung auch in der alten Version des XAMPP, verschwand dann aber als ich dieses output_buffering gesetzt habe.
Einem LAMP scheint dies wohl überhaupt nicht zu interessieren - von Anfang an.

Ich denke, das Problem ist hiermit gelöst.
Interessant wäre jedoch zu wissen, warum es gerade der XAMPP an dieser Stelle so genau nimmt.

Gruß,
Leeloo
Leeloo5E
 
Posts: 37
Joined: 16. April 2006 16:55

Postby Scory » 26. February 2008 16:51

>Scheinbar ist das Pfuschen mit output_buffering auch nur im verfuschten XAMPP nötig, denn der normale Apache2 unter Linux akzeptiert den PHP-Quellcode so wie er ist.

So ein Dummgelalle! Verpfuscht sind allenfalls Deine Scripts - ich benutze sowohl Xampp (unter Windows und Linux) also auch selbstinstallierte Apaches und MySQL bzw. PHP (auch sowohl unter Windows wie Linux).

Die verhalten sich (wenig überraschend) alle gleich - weil es die gleichen Programme sind.

@Scory:
ja, auch das verursacht unter XAMPP ein kaputtes RTF.
Versuch doch mal ein heiles RTF per XAMPP runterzuladen. Selbes Problem wie oben beschrieben: RTF wird nicht als RTF dargestellt. Es liegt also nicht an meine Code, sondern an der XAMPP-Konfiguration.


Es liegt an deinem Code und NUR an Deinem Code - Xampp ist NICHTS anderes als ein Original-Apache und Original-MySQL und Original-PHP. Allenfalls benutzt Du verschiedene Konfigurationsdateien, die mal mehr, mal weniger Fehlermeldungen produzieren.

Dieser Fehler, den Du hier fabrizierst, geht ausschließlich zu Lasten eines fehlerhaften Scripts - das ist so sicher wie das Amen in der Kirche.

Natürlich ist es einfacher, seine eigene Unzulänglichkeit auf Drittkomponenten abzuwälzen. Aber davon wird Dein Script nicht besser.

P.S.:
Hierbei reicht es aus, wenn ein auskommentiertes echo mit HTML-Tags vorher irgendwo steht. Und schon mag mich der Xampp nicht mehr.


Huahua - ich könnte schreien!! Ja, das ist ein fetter Fehler von DIR. NUR VON DIR! Das hat mit Xampp NICHTS(!!!) zu tun. Genau das, was ich vermutet hatte - irgendwo ein blinder Output. Ein Kommentar ist und war immer schon auf allen PHP-Versionen und allen Apacheversionen ein HTTP-Output - ohne wenn und ohne aber!

P.P.S.:
Komischerweise kam diese Fehlermeldung auch in der alten Version des XAMPP, verschwand dann aber als ich dieses output_buffering gesetzt habe.


Und haargenau, wie ich es gesagt habe - "komischerweise" verschwindet die Fehlermeldung, wenn man output-buffering einschaltet. Du solltest dringend Deine mangelhaften Kenntnisse über das Protokoll HTTP, über PHP und die header()-Funktion verbessern - dann wäre Dir das nicht passiert.
Scory
 

Postby Leeloo5E » 26. February 2008 17:09

Oh, danke, dass du mir das nochmal so unter die Nase reibst. Hat dir wohl nicht ausgereicht, dass ich schon in meinem eigenen Beitrag zugegeben habe, dass es dann doch an meinem Skript lag. Aber wenn du richtig gelesen hast, an einem auskommentierten, der normalerweise eben NICHT ausgegeben werden soll, da er sowieso nur für Debug-Zwecke genutzt wird.
Hier an dieser Stelle mag XAMPP nicht unbedingt der Schuldige gewesen sein, doch an anderer Stelle bestimmt.
Ich nutze ebenfalls XAMPP sowohl unter Linux als Windows und auch einen normalen Apachen unter Linux. Wobei ich den Weg zu letzterem fand, weil der XAMPP unter Linux ein bekanntes Problem hatte, welches es mir unmöglich machte, ihn zu verwenden. Das zeigt, dass XAMPP mit LAMP keineswegs vergleichbar bzw. identisch ist. Genau das Gegenteil ist der Fall. Schon deshalb sollte man sich überlegen XAMPP einzusetzen. Produktiv nur in wirklich abesichteren Umgebungen, denn XAMPP ist und bleibt eine Entwicklerumgebung, die für den offenen produktiven Einsatz viel zu unsicher ist, trotz der vorgeblichen Sicherheit von wegen angeben von Passwörtern für mysql etc.

So, jetzt Schluss mit Diskutieren. Das würde hier irgendwann in einer Grundsatzdiskusion enden. An der ich mich nun nicht weiter beteiligen werde und will.

Vielen Dank für die Beteiligung an der Diskusion und Hilfestellung. Allerdings konnte mir keiner sagen, dass es am auskommentierten echo bzw. und eigentlich an der Zeichenkodierung der PHP-Datei liegt. So dass hier wohl auch noch jemand Hausaufgaben machen muss ;-)

Schönen Feierabend dann noch.
Leeloo5E
 
Posts: 37
Joined: 16. April 2006 16:55

Next

Return to PHP

Who is online

Users browsing this forum: No registered users and 4 guests