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?
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.

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?
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.
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?
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.
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
Een BOM wordt gewoon behandeld als elke andere tekst die je voor de < ?php open zet: als output naar de browser.
Thomas van den Heuvel op 09/06/2020 23:19:47

[quote="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? ...
[/quote]
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

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!


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?
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
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.

Reageren