Vermijden van BOM (Byte Order Marker) bij downloaden

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 volgende »

Hubert Christiaen

Hubert Christiaen

09/06/2020 17:03:55
Quote Anchor link
Ik heb 2 scripts waarbij uit een database met gegevens van leden een bestand gemaakt wordt om rechtstreeks te downloaden. Hiervoor wordt beroep gedaan op:
header('Content-disposition: attachment; filename = boekje.rtf;');
ofwel op:
header('Content-disposition: attachment; filename = tblleden.csv');

In het laatste geval loopt alles naar wens. In het eerste geval echter wordt er aan het begin van het bestand een BOM of "Byte order marker" toegevoegd zodat het bestand niet meer herkend wordt als rtf-bestand door MS Word of Libre Office Writer. Ik zie niet waarom er in het laatste geval niets toegevoegd wordt aan het bestand en in het eerste wel. Ik heb al geprobeerd met een tweede header:
header('Content-type:application/rtf; charset=latin1;');
maar niets helpt.

Ik heb voorlopig het probleem opgelost door het rtf-bestand naar een tijdelijk bestand te schrijven via fwrite en dat bestand dan aan te bieden voor download. fwrite genereert geen BOM.

Iemand een idee?
 
PHP hulp

PHP hulp

20/04/2024 08:39:45
 
Thomas van den Heuvel

Thomas van den Heuvel

09/06/2020 17:15:36
Quote Anchor link
Sja, hoe wordt het bestand gegenereerd?
En zou je niet een zwik meer headers moeten meegeven (evt. Content-Description, ik zou wellicht voor Content-Type application/octet-stream kiezen omdat je dan een download forceert, ook al is het bestandstype bekend/is er een applicatie die deze kan lezen, Content-Transfer-Encoding etc)?

Het lijkt mij echter niet dat op grond van de headers het bestand inhoudelijk wordt aangepast.

Quote:
Ik zie niet waarom er in het laatste geval niets toegevoegd wordt aan het bestand en in het eerste wel.

Ben je hier geen appels met peren aan het vergelijken? Dit zijn twee verschillende bestandstypen, dus deze worden mogelijk op verschillende manieren opgebouwd, wat opnieuw de vraag doet rijzen, hoe worden deze gegenereerd?
 
Hubert Christiaen

Hubert Christiaen

09/06/2020 17:53:44
Quote Anchor link
De tekst van het bestand wordt aangemaakt via echo of printinstructies, net zoals men dat zou doen voor een tekst die op het scherm moet verschijnen. Voor het RTF-bestand begint die tekst natuurlijk met

{\rtf1
{\fonttbl{\f0 Calibri;}}
\paperw11906\paperh16838\margl1650\margr1200\margt1300\margb1100\footery560
\margmirror
\pard\qc\fs36{\b Lijst van de leden\par\par}
\trowd\trqc\cellx7020
\pard\qc\fs26 De leden die van adres veranderen, worden verzocht hiervan
\line zo spoedig mogelijk opgave te doen aan de Secretaris,
....
maar dat heeft voor de computer toch geen belang.
 
Thomas van den Heuvel

Thomas van den Heuvel

09/06/2020 18:13:31
Quote Anchor link
PHP voegt volgens mij zelf niet automatisch een BOM toe.

Het probleem is mogelijk ook niet de BOM zelf, maar de verdere encoding.

Of de applicatie die de bestanden probeert te lezen, in combinatie met de encoding.

Misschien heb je meer success om e.e.a. op te slaan als UTF-16LE in plaats van UTF-8 (zie de laatste link hieronder).

Maar misschien zou je in eerste instantie kunnen proberen om de BOM te strippen.

Volgens een andere bron voegt Excel deze karakters mogelijk zelf toe?
 
Rob Doemaarwat

Rob Doemaarwat

09/06/2020 20:19:06
Quote Anchor link
Zit er niet gewoon een BOM op je PHP script (dus voor de open < ? p h p)? Die komt dan voor de output die je met print() genereert. Bij een fwrite() schrijf je enkel de data weg die je bedoelt.

Bij een CSV zal dit niet zo'n probleem geven (toch een tekst formaat); bij een RTF (blijkbaar) wel.

Loop dus alle PHP files langs die je gebruikt (dus ook via-via-via include) en verwijder evt. BOM-ers.
Gewijzigd op 09/06/2020 20:19:47 door Rob Doemaarwat
 
Thomas van den Heuvel

Thomas van den Heuvel

09/06/2020 23:19:47
Quote Anchor link
Rob Doemaarwat op 09/06/2020 20:19:06:
Zit er niet gewoon een BOM op je PHP script (dus voor de open < ? p h p)? Die komt dan voor de output die je met print() genereert.

Is dat zo? Je serveert toch niet het rauwe PHP-bestand? Wordt, als het PHP-bestand een BOM heeft, deze overgenomen naar de output die de webserver produceert? o_O
 
Rob Doemaarwat

Rob Doemaarwat

09/06/2020 23:29:41
Quote Anchor link
Een BOM wordt gewoon behandeld als elke andere tekst die je voor de < ?php open zet: als output naar de browser.
Gewijzigd op 09/06/2020 23:29:53 door Rob Doemaarwat
 
Ozzie PHP

Ozzie PHP

10/06/2020 00:24:59
Quote Anchor link
Thomas van den Heuvel op 09/06/2020 23:19:47:
Rob Doemaarwat op 09/06/2020 20:19:06:
Zit er niet gewoon een BOM op je PHP script (dus voor de open < ? p h p)? Die komt dan voor de output die je met print() genereert.

Is dat zo? ...

Ja, alles wat niet tussen php tags staat wordt gewoon naar de browser gestuurd (mits er nog geen headers zijn verzonden), dus ook een BOM-character.

Test.php
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
Hallo allemaal!

<?php

echo 'Hier zijn Bassie en Adriaan.<br><br>';

?>

Allememaggies!

Levert in de browser zoiets op als:

Hallo allemaal!

Hier zijn Bassie en Adriaan.

Allememaggies!
 
Ad Fundum

Ad Fundum

10/06/2020 09:01:12
Quote Anchor link
Ik heb een soortgelijk probleem gehad. Als als je een bestand voor Office maakt dan verwacht Office een bestand met een BOM, maar de browser haalde de BOM weg bij het downloaden. In mijn geval kon ik het aan de praat krijgen door bij downloads 2x een BOM te versturen.
Er zijn verschillen in versies van Office, en misschien ook wel in browsers.

Welke versie van Office en welke browser gebruik je?
Gewijzigd op 10/06/2020 09:09:24 door Ad Fundum
 
Hubert Christiaen

Hubert Christiaen

10/06/2020 11:20:13
Quote Anchor link
Er is geen BOM aanwezig op mijn script.

Ik heb de gegenereerde tekst bekeken in hexadecimaal en de BOM is van de vorm EF BB BF. Dit is de vorm voor een utf-8 bestand, alhoewel er een charset=latin1 gegeven is. De conversie naar latin1 wordt correct uitgevoerd voor de verdere gegevens.

Het enige verschil tussen beide scripts is dat bij het csv script ALLE output uit een database gehaald wordt en bij het rtf script wordt gestart met een kop die als constante toegekend wordt aan een variabele. Als de broncode van het script in utf-8 is, is die tekst natuurlijk ook in utf-8. Maar omzetten van het script naar latin1 verandert niets aan de zaak en ook alles in utf-8 zetten (script en output van de database) verandert niets.

Ook een andere functie gebruiken dan echo, zoals printf, verandert niets.

Dit hangt duidelijk niet af van de browser. Testen met Chromium en Firefox geven hetzelfde resultaat. Er wordt trouwens geen iota getoond in de browser.

(Open) Office toont de broncode. Office beschouwt het bestand dus als een gewoon tekstbestand. MS Word kan er niets mee aanvangen. Het stelt voor om het bestand te openen met "Openen en herstellen", maar ook dat levert niets op.

Niettemin bedankt voor de suggesties.
Hubert
Gewijzigd op 10/06/2020 11:24:07 door Hubert Christiaen
 
Thomas van den Heuvel

Thomas van den Heuvel

10/06/2020 13:10:51
Quote Anchor link
Ik zou de eindprogramma's als uitgangspunt nemen.

Wat voor eisen stellen deze aan formaat, character encoding et cetera.

Het heeft geen zin om dingen aan de PHP-kant aan te passen zolang dit niet voldoet aan het formaat dat het verwerkende programma verwacht. Ga dus na wat voor standaarden werken/of in welke programma's je deze bestanden wilt gebruiken en aan welke eisen dat moet voldoen, en giet je bestanden vervolgens in dat formaat. Begin bij het einde.
 
Hubert Christiaen

Hubert Christiaen

10/06/2020 17:19:18
Quote Anchor link
Het is zeer eenvoudig wat het eindproduct moet zijn: zowel csv- als rtf-bestanden zijn zuivere tekstbestanden, juist zoals ook een html- of een xml-bestand
 
Thomas van den Heuvel

Thomas van den Heuvel

10/06/2020 19:23:17
Quote Anchor link
Dan zou ik eens kijken wat gebruikelijk is qua encoding. Ook kun je in RTF zelf een character encoding specificeren en/of Unicode karakters opnemen met \u.

Hoe genereer je deze bestanden trouwens? Doe je dit on-the-fly (het script serveert direct een gegenereerd bestand) of bak je echt een bestand wat je vervolgens gebruikt? Hoe dan ook, eventuele headers in jouw PHP-script worden niet aan het bestand "gekoppeld" en gaan dus verloren. Het lijkt mij handiger dat de bestanden wat dat betreft op zichzelf staan en ofwel een standaard encoding voor dat formaat gebruiken ofwel dat er een (toegestane) encodering staat vermeld in (en wordt toegepast op) de inhoud.

Hubert Christiaen op 10/06/2020 17:19:18:
zuivere tekstbestanden


Mja, maar There Ain’t No Such Thing As Plain Text.
 
Jan R

Jan R

10/06/2020 19:39:01
Quote Anchor link
Hubert Christiaen op 10/06/2020 11:20:13:
Er is geen BOM aanwezig op mijn script.

Ik heb de gegenereerde tekst bekeken in hexadecimaal en de BOM is van de vorm EF BB BF. Dit is de vorm voor een utf-8 bestand,


Dus wel een bom :)
Gebruik een goede tekst editor om uw php bestand om te zetten naar "zonder bom"
In notepad++ karakterset ==> converteer naar utf-8 zonder BOM

Jan
 
Hubert Christiaen

Hubert Christiaen

11/06/2020 11:51:37
Quote Anchor link
Jan R op 10/06/2020 19:39:01:
Hubert Christiaen op 10/06/2020 11:20:13:
Er is geen BOM aanwezig op mijn script.

Ik heb de gegenereerde tekst bekeken in hexadecimaal en de BOM is van de vorm EF BB BF. Dit is de vorm voor een utf-8 bestand,

Dat zijn dus 2 verschillende zaken!
De BOM weghalen na het downloaden is vijgen na Pasen. De gewone bezoeker moet een bestand zonder BOM krijgen.
 
Rob Doemaarwat

Rob Doemaarwat

11/06/2020 15:41:20
Quote Anchor link
EF BB BF is "de BOM" in UTF8: https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 . Als je die ziet zit er dus toch een BOM ergens in je code. Wat Jan dus bedoelt is dat je niet de gebruiker het eindproduct met Notepad++ an het knutselen moet sturen, maar dat je *zelf* aan de slag moet om toch "ergens" een BOM van een PHP bestand af te slopen.
 
Hubert Christiaen

Hubert Christiaen

11/06/2020 18:08:27
Quote Anchor link
Er zit geen BOM bij het begin van mijn script een er zit geen BOM bij het begin van de tekstconstante die het begin van de rtf-code bevat.

Als ik dezelfde code gebruik, maar de outputinstructies vervang door schrijven naar een bestand via fwrite i.p.v. via echo te schrijven naar het "scherm", dan krijg ik een bestand zonder BOM. Het is dus ergens in de keten naar de uitvoer dat er een BOM bijgevoegd wordt als ik rechtstreeks laat downloaden.

De code die gebruikt wordt voor de gegevens uit de database is windows-1252, zonder enige escaping voor accentletters en dat werkt correct (expliciet ingesteld met een mysqli_set_charset() ).

De informatie in de header-functie wordt niet doorgegeven aan het bestand maar zou normaal invloed moeten hebben op de codering waarmee naar het "scherm" geschreven en wordt. Ik heb die header-functie trouwens reeds zeer veel gebruikt om servers die zich niet houden aan de html-instructie voor het opgeven van een charset, toch tot de orde te roepen. Hier wordt er toch iets bijgevoegd dat helemaal niet hoort bij de opgegeven codering.
 
Jan R

Jan R

11/06/2020 18:44:48
Quote Anchor link
Heb je Rob zijn link wel gelezen. JE ZIET EEN BOM NIET. Het zijn "verborgen" code/gegevens je dient dus het aangeroepen php-bestand te verbeteren zoals ik schreef in mijn vorig antwoord. Dus niet het resultaat uit de browser maar het script zelf. Mogelijks ook andere ge-include bestanden als die er zijn.
 
Rob Doemaarwat

Rob Doemaarwat

11/06/2020 19:54:08
Quote Anchor link
Ik zal het even uitschrijven voor je:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
//zo ziet je PHP bestand er uit
EF BB BF <?php

$rtf
= '...'; //RTF data (zonder BOM)

file_put_contents($filename,$rtf); //$rtf zoals ie bedoeld is, zonder BOM

print($rtf); //je browser ontvangt nu de $rtf MET DE BOM DIE JE HIERBOVEN VOOR
             //DE PHP-OPEN-TAG ZIET STAAN

?>

Het is dus "logisch" dat er in de RTF-als-bestand *geen* BOM zit, terwijl je 'm er in de RTF-als-een-download wel bij "krijgt". Dit is dus precies wat jij nu ziet gebeuren, en zou dus ook precies moeten "verklaren" dat je ergens in de kop van je één van je PHP scripts een BOM hebt zitten.
Gewijzigd op 11/06/2020 19:55:06 door Rob Doemaarwat
 
Hubert Christiaen

Hubert Christiaen

12/06/2020 09:58:39
Quote Anchor link
Jan R: "Je ziet een BOM niet"
Je kan een BOM erl zien:
- zeker als je het bestand hexadecimaal bekijkt.
- als je een editor gebruikt die weet wat een BOM is. Dan krijg je een menu-optie die je zegt dat er een BOM aanwezig is en die je eventueel toelaat om die te verwijderen.
- als je editor of tekstverwerker niet weet wat een BOM is, dan wordt die afgedrukt als niet-afdrukbaar tken of als rare tekens. In MS Word ingelezen als "tekst zonder opmaak" krijg je bv. iets als: {\rtf1

Rob Doemaarwat:
Ik gebruik de header-functie. Als je dan ook maar iets voor de openingstag "<..." zet, krijg je een fatale fout met als commentaar "Output already sent before header". Al ooit met die header-functie gewerkt?

Lees a.u.b. aandachtig wat reeds gezegd is vooraleer met simplistische verklaringen te komen.
Gewijzigd op 12/06/2020 09:59:50 door Hubert Christiaen
 
Rob Doemaarwat

Rob Doemaarwat

12/06/2020 10:13:09
Quote Anchor link
Hé wijsneus, als je alles zo goed weet, waarom los je het zelf dan niet op?

"Misschien" (hé, ik probeer ook maar te helpen) gebeurt er iets van het volgende:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
<?php

header('Weet-veel-wat: Doe-maar-wat');

include('file-met-stiekem-toch-een-BOM.php');

print($rtf);

?>

Header: werkt / geen foutmeldingen
Maar toch een BOM in je output.

Heb je misschien al de moeite genomen om gewoon eens door al je files heen te gaan (met een tooltje hè*, niet met een HEX-editor alle bestanden gaan zitten bekijken) op zoek naar die EF BB BF, in plaats van maar steeds met je voeten te gaan staan stampen, en vol te houden dat *er geen BOM in zit*?

* bijvoorbeeld in Linux:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
grep -rlI $'\xEF\xBB\xBF' .
(incl de punt)
Gewijzigd op 12/06/2020 14:12:20 door Rob Doemaarwat
 

Pagina: 1 2 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.