Client-Side Operations with Local Files
Part 3. FileReader Methods
Reading File As Text
We will demonstrate the read methods by performing some practical tasks related to File manipulations. Our first task will comprise reading a local text file and displaying its contents in a <textarea>. To present the file data as a text string, the FileReader exposes the readAsText() method accepting two parameters. The first one is an object implementing Blob. The second is an optional string pointing to an IANA-approved character set, e.g. UTF-8 or ISO-8859-1. The following example will bring the readAsText() method into action:
file control and text container
<input type="file" name="file-control" accept="text/plain" onchange="displayText(this.files[0])">
<textarea id="text-container" readonly></textarea>
FileReader instantiation
var fileReader=new FileReader();
var textArea=document.getElementById("text-container");
calling readAsText() method
function displayText(file) {
fileReader.onload=loadHandler;
fileReader.readAsText(file);
}
load event handler
function loadHandler(event) {
textArea.style.width="650px";
textArea.style.height="390px";
textArea.textContent=event.target.result; // or this.result
}
In this example a load event listener has been attached to a FileReader instance, then the readAsText() method has been called. If a file is read successfully, its contents are returned as the result property of the FileReader.
Reading File As ArrayBuffer
Reading a file as a text may prove insufficient if an application requires more low-level approach to file contents. The readAsArrayBuffer() method allows client scripts to read file data straight in its native form. The method returns a file as an ArrayBuffer instance which can be further passed to a routine dealing with raw bytes. In the example below, the first page of a local PDF file is displayed on the canvas surface. The file is originally represented as a binary buffer:
file control and PDF container
<input type="file" name="file-control" accept="application/pdf" onchange="displayPDF(this.files[0])">
<canvas id="pdf-container"></canvas>
FileReader instantiation
var fileReader=new FileReader();
var canvas=document.getElementById("pdf-container");
var context=canvas.getContext("2d");
reading PDF file as ArrayBuffer
function displayPDF(file) {
fileReader.onload=loadHandler;
fileReader.readAsArrayBuffer(file);
}
load event handler
function loadHandler(loadEvent) {
var buffer=this.result;
PDFJS.getDocument(buffer).then(obtainPDF, failure);
}
Promise to get the PDF file is fulfilled
function obtainPDF(pdfObj) {
pdfObj.getPage(1).then(viewPage, failure);
}
Promise to get access to the first page of the PDF file is fulfilled
function viewPage(page) {
var viewport=page.getViewport(2.0);
canvas.width=viewport.width;
canvas.height=viewport.height;
var renderingContext={canvasContext: context, viewport: viewport};
page.render(renderingContext);
}
Promise is rejected
function failure(errObj) {
console.error(errObj);
}
The example is based on Mozilla's PDF.js library which, in its turn, relies on the Promises API. After a selected file is passed as an ArrayBuffer to the static PDFJS.getDocument() method, a new Promise is instantiated. It represents the result of the asynchronous load of all PDF objects constituting the file. The then() method of the Promise has two arguments: these are named functions reflecting the state of the operation. If the file is parsed successfully, the obtainPDF() callback is invoked. The code of the function tries to obtain access to the first page of the document. As a result, another Promise is created. If the Promise is fulfilled, the viewPage() is called. Both Promises share the same error handler: the failure() function is invoked if any of the Promises is rejected.
Reading File As Data URL
The last aim is to get the Base64-encoded representation of a file as part of the data: URL scheme. When a code snippet makes use of the readAsDataURL() method, it retrieves the result in the form of data:valid_MIME_type;base64,encoded_file_data. In the example below, a new image element will get its source as a data: URL.
file control for picking out an image
<input type="file" name="file-control" accept="image/*" onchange="showImage(this.files[0])">
FileReader instantiation
var fileReader=new FileReader();
reading an image as data: URL
function showImage(file) {
fileReader.onload=loadHandler;
fileReader.readAsDataURL(file);
}
load event handler
function loadHandler(event) {
var img=new Image();
img.src=this.result;
document.body.appendChild(img);
}