HTML5 File API read as text and binary
2022 update: See explanation below for why the OP was seeing what they were seeing, but the code there is outdated. In modern environments, you'd use the methods on the Blob
interface (which File
inherits):
arrayBuffer
for reading binary data (which you can then access via any of the typed arrays)text
to read textual datastream
for getting aReadableStream
for handling data via streaming (which allows you to do multiple transformations on the data without making multiple passes through it and/or use the data without having to keep all of it in memory
Once you have the file from the file input (const file = fileInput.files[0]
or similar), it's literally just a matter of:
await file.text(); // To read its text
// or
await file.arrayBuffer(); // To read its contents into an array buffer
(See ReadableStream
for an example of streams.)
You might access the array buffer via a Uint8Array
(new Uint8Array(buffer)
).
Here's an example of text
and arrayBuffer
:
const $ = id => document.getElementById(id);
const fileInput = $("fileInput");
const btnRead = $("btnRead");
const rdoText = $("rdoText");
const contentsDiv = $("contents");
const updateButton = () => {
btnRead.disabled = fileInput.files.length === 0;
};
const readTextFile = async (file) => {
const text = await file.text();
contentsDiv.textContent = text;
contentsDiv.classList.add("text");
contentsDiv.classList.remove("binary");
console.log("Done reading text file");
};
const readBinaryFile = async (file) => {
// Read into an array buffer, create
const buffer = await file.arrayBuffer();
// Get a byte array for that buffer
const bytes = new Uint8Array(buffer);
// Show it as hex text
const lines = [];
let line = [];
bytes.forEach((byte, index) => {
const hex = byte.toString(16).padStart(2, "0");
line.push(hex);
if (index % 16 === 15) {
lines.push(line.join(" "));
line = [];
}
});
contentsDiv.textContent = lines.join("\n");
contentsDiv.classList.add("binary");
contentsDiv.classList.remove("text");
console.log(`Done reading binary file (length: ${bytes.length})`);
};
updateButton();
fileInput.addEventListener("input", updateButton);
btnRead.addEventListener("click", () => {
const file = fileInput.files[0];
if (!file) {
return;
}
const readFile = rdoText.checked ? readTextFile : readBinaryFile;
readFile(fileInput.files[0])
.catch(error => {
console.error(`Error reading file:`, error);
});
});
body {
font-family: sans-serif;
}
#contents {
font-family: monospace;
white-space: pre;
}
<form>
<div>
<label>
<span>File:</span>
<input type="file" id="fileInput">
</label>
</div>
<div>
<label>
<input id="rdoText" type="radio" name="format" value="text" checked>
Text
</label>
<label>
<input id="rdoBinary" type="radio" name="format" value="binary">
Binary
</label>
</div>
<div>
<input id="btnRead" type="button" value="Read File">
</div>
</form>
<div id="contents"></div>
HTML5 File API readAsBinaryString reads files as much larger, different than files on disk
This is probably because you're reading the file as a binary string and constructing the multipart/form-data
request manually. For one, you don't need to use FileReader
.
Since you just want to send the content, try using xhr.send(File)
or xhr.send(FormData)
. The latter constructs and sends a multipart/form-data
for you:
function uploadFiles(url, files) {
var formData = new FormData();
for (var i = 0, file; file = files[i]; ++i) {
formData.append(file.name, file);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function(e) { ... };
xhr.send(formData); // multipart/form-data
}
document.querySelector('input[type="file"]').onchange = function(e) {
uploadFiles('/server', this.files);
};
HTML5 Binary File Writing w/ Base64
I wrote an extension that captures a screenshot using Chrome, puts it on a canvas, resizes it, then saves the canvas data using the Filesystem API. Not sure if this is directly similar to yours, but perhaps most of the code will suffice?
In this case, I assume my dataURI
(eg myCanvas.toDataURL("image/png")
) would be the same Base64 format as your dataInBase64Format
.
Function:
// canvas.toBlob is not implemented in Chrome yet! So we have to build the blob ourselves.
// Derived from http://mustachified.com/master.js
// via http://lists.whatwg.org/pipermail/whatwg-whatwg.org/2011-April/031243.html
// via https://bugs.webkit.org/show_bug.cgi?id=51652
// via http://code.google.com/p/chromium/issues/detail?id=67587
function dataURItoBlob(dataURI, callback) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var bb = new window.WebKitBlobBuilder();
bb.append(ab);
return bb.getBlob(mimeString);
}
Usage:
// Save image data
function onInitFs(fs){
fs.root.getFile(fileName, {create:true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.write(dataURItoBlob(myCanvas.toDataURL("image/png")));
}, fileErrorHandler);
}, fileErrorHandler);
}, fileErrorHandler);
Saving binary data as file using JavaScript from a browser
This is possible if the browser supports the download
property in anchor elements.
var sampleBytes = new Int8Array(4096);
var saveByteArray = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, name) {
var blob = new Blob(data, {type: "octet/stream"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = name;
a.click();
window.URL.revokeObjectURL(url);
};
}());
saveByteArray([sampleBytes], 'example.txt');
JSFiddle: http://jsfiddle.net/VB59f/2
html5 fileReader -- how to only read the first N characters of a file?
You can use the .slice
method. You can read more here
var reader = new FileReader();
reader.onloadend = function(evt)
{
if (evt.target.readyState == FileReader.DONE) // DONE == 2
{
alert(evt.target.result);
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
how to read a text file using javascript without using activeX?
we can do that using HTML5 fileAPI - FileReader.ReadAsText
HTML5 File API read as text and binary
Related Topics
Executing ≪Script≫ Injected by Innerhtml After Ajax Call
How to Load an HTML Page in a Div Using JavaScript
Why Does My Http://Localhost Cors Origin Not Work
How to Create a ≪Style≫ Tag With JavaScript
Check If an Element Contains a Class in JavaScript
Jquery/JavaScript Collision Detection
How to Change an Element'S Text Without Changing Its Child Elements
Where to Place JavaScript in an HTML File
Frame Buster Buster ... Buster Code Needed
Check If Checkbox Is Checked With Jquery
How to Escape HTML Special Chars in JavaScript
Why Js Function Name Conflicts With Element Id
Full-Screen Iframe With a Height of 100%
Adjust Width and Height of Iframe to Fit With Content in It
Height Equal to Dynamic Width (Css Fluid Layout)
Return HTML Content as a String, Given Url. JavaScript Function