J'essaie d'enregistrer un fichier CSV à l'aide de JavaScript, avec une nomenclature UTF-8 ajoutée au début. Cependant, lors de la vérification du fichier téléchargé, il semble que la nomenclature est toujours supprimée. Le code suivant reproduit le problème:
var csv = '\ufeff\ufefftest,test2';
L'ajout du caractère BOM à la chaîne deux fois produit le résultat correct:
var csv = '\ufefftest,test2'; var blob = new Blob([csv], {type: 'text/csv;charset=utf-8'}); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'test.csv'; document.body.appendChild(a); a.click();
Le fichier résultant doit avoir le caractère BOM au début. p >
Pourquoi est-il supprimé dans cet exemple?
EDIT: Mon cas d'utilisation génère un fichier CSV et s'assure que le fichier peut être ouvert avec un encodage correct par Microsoft Excel. Je pense que la nomenclature est peut-être détectée et tronquée, mais Excel a besoin que le caractère soit présent pour détecter UTF-8.
3 Réponses :
Ma meilleure hypothèse est que certains navigateurs peuvent interpréter la nomenclature dans le texte et la tronquer.
J'ai ajouté un exemple où la nomenclature est ajoutée par un ArrayBuffer
au Blob . Cela semble fonctionner.
Mais sachez que la nomenclature que vous essayez d'ajouter est la nomenclature UTF-16 (BE)
pas la nomenclature UTF-8 EF BB BF
.
https://de.wikipedia.org/wiki/Byte_Order_Mark
var csv = 'test,test2'; // create BOM UTF-8 var buffer = new ArrayBuffer(3); var dataView = new DataView(buffer); dataView.setUint8(0, 0xfe); dataView.setUint8(1, 0xbb); dataView.setUint8(2, 0xbf); var read = new Uint8Array(buffer); // create BOM UTF-16 var buffer = new ArrayBuffer(2); var dataView = new DataView(buffer); dataView.setUint8(0, 0xfe); dataView.setUint8(1, 0xff); var read = new Uint8Array(buffer); var blob = new Blob([read /*prepend bom*/, csv], {type: 'text/csv;charset=utf-8'}); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'test.csv'; document.body.appendChild(a); a.click();
Lors de l'ouverture du fichier résultant dans Emacs, il ne semble pas détecter l'encodage UTF-8, affichant simplement 3 caractères de jeu de caractères latins pour ces points de code.
Comme je l'ai dit dans la réponse, le BOM FEFF n'est PAS le BOM UTF-8 mais le UTF-16 (BE).
Votre nomenclature est ici.
C'est simplement que tout ce que vous utilisez pour le lire le supprime, puisque, eh bien, il ne devrait pas faire partie du texte.
Cependant, si vous effectuez un vidage HEX ou le lisez comme un ArrayBuffer, vous verrez qu'il est toujours là:
<br><label>you can reupload it here too<input type="file" id="inp"></label>
const csv = '\ufefftest,test2'; const blob = new Blob([csv], {type: 'text/csv;charset=utf-8'}); download(blob); read(blob); inp.onchange = e => read(inp.files[0]); async function read(blob) { // grab the byte content const buf = await new Response(blob).arrayBuffer(); // stupidly map to some string characters const str = [...new Uint8Array(buf)] .map(c => String.fromCharCode(c)); // only for the demo, this doesnt convert from bytes to string in UTF-8! console.log(str); } function download(blob) { const a = document.createElement('a'); a.download = 'file.csv'; a.href = URL.createObjectURL(blob); a.textContent = 'download'; document.body.prepend(a); }
Et notez que l'autre réponse est juste en ce que votre nomenclature est en fait celle de UTF-16BE, mais ce n'est pas encore votre problème.
var csv = 'test,test2'; var blob = new Blob([decodeURIComponent('%ef%bb%bf') /*prepend bom*/, csv], {type: 'text/csv;charset=utf-8'}); var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.href = url; a.download = 'test.csv'; document.body.appendChild(a); a.click();
Cela se produit-il dans plusieurs navigateurs? Que se passe-t-il si vous ne spécifiez pas de jeu de caractères?
@OllyHodgson Cela se produit dans Firefox et Chrome