HTML5 - Cómo Leer Archivos en JavaScript
HTML5 - Cómo Leer Archivos en JavaScript
A continuación se indican las interfaces que ofrece la especificación para acceder a archivos desde un
sistema de archivos "local".
1. File: representa un archivo individual que proporciona información de solo lectura (por ejemplo, el
nombre, el tamaño del archivo, el tipo MIME y una referencia al control del archivo).
2. FileList: representa una secuencia de conjunto de objetos File (tanto la secuencia <input type="file"
multiple> como arrastrar un directorio de archivos desde el escritorio se consideran ejemplos de
esta interfaz).
3. Blob: permite fragmentar un archivo en intervalos de bytes.
Cuando se utiliza junto con las estructuras de datos anteriores, la interfaz de FileReader se puede utilizar
para leer un archivo de forma asíncrona mediante el control de eventos de JavaScript. Por lo tanto, se
puede controlar el progreso de una lectura, detectar si se han producido errores y determinar si ha
finalizado una carga. El modelo de evento de XMLHttpRequest guarda muchas semejanzas con las API.
Nota: en el momento de redactar este tutorial, las API necesarias para trabajar con archivos locales son
compatibles con Chrome 6.0 y Firefox 3.6. A partir de Firefox 3.6.3, no se admite el método File.slice().
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
<script>
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files; // FileList object.
// files is a FileList of File objects. List some properties.
var output = [];
for (var i = 0, f; f = files[i]; i++) {
output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ',
f.size, ' bytes, last modified: ',
f.lastModifiedDate.toLocaleDateString(), '</li>');
}
document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>';
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy.
}
// Setup the dnd listeners.
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
</script>
Nota: algunos navegadores tratan los elementos <input type="file"> como destinos donde soltar
archivos nativos. Intenta arrastrar los archivos al campo de introducción de contenido del ejemplo
anterior.
A continuación se indican las cuatro opciones de lectura asíncrona de archivo que incluye FileReader.
Una vez que se ha activado uno de estos métodos de lectura en el objeto FileReader, se pueden utilizar
los eventos onloadstart, onprogress, onload, onabort, onerror y onloadend para realizar un seguimiento
de su progreso.
En el ejemplo que se muestra a continuación, se excluyen las imágenes de los elementos seleccionados
por el usuario, se activa reader.readAsDataURL() en el archivo y se muestra una miniatura estableciendo
una URL de datos como valor del atributo "src".
<style>
.thumb {
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}
</style>
<script>
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class="thumb" src="', e.target.result,
'" title="', escape(theFile.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
if (file.webkitSlice) {
var blob = file.webkitSlice(startingByte, endindByte);
} else if (file.mozSlice) {
var blob = file.mozSlice(startingByte, endindByte);
}
reader.readAsBinaryString(blob);
<style>
#byte_content {
margin: 5px 0;
max-height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
#byte_range { margin-top: 5px; }
</style>
<button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>
<script>
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
document.getElementById('byte_content').textContent = evt.target.result;
document.getElementById('byte_range').textContent =
['Read bytes: ', start + 1, ' - ', stop + 1,
' of ', file.size, ' byte file'].join('');
}
};
if (file.webkitSlice) {
var blob = file.webkitSlice(start, stop + 1);
} else if (file.mozSlice) {
var blob = file.mozSlice(start, stop + 1);
}
reader.readAsBinaryString(blob);
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
var startByte = evt.target.getAttribute('data-startbyte');
var endByte = evt.target.getAttribute('data-endbyte');
readBlob(startByte, endByte);
}
}, false);
</script>
Los eventos onloadstart y onprogress se pueden utilizar para controlar el progreso de una lectura.
En el ejemplo que aparece a continuación, se muestra una barra de progreso que permite controlar el
estado de la lectura. Para ver cómo funciona el indicador de progreso, intenta utilizar un archivo grande
o un archivo de una unidad remota.
<style>
#progress_bar {
margin: 10px 0;
padding: 3px;
border: 1px solid #000;
font-size: 14px;
clear: both;
opacity: 0;
-moz-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-webkit-transition: opacity 1s linear;
}
#progress_bar.loading {
opacity: 1.0;
}
#progress_bar .percent {
background-color: #99ccff;
height: auto;
width: 0;
}
</style>
<script>
var reader;
var progress = document.querySelector('.percent');
function abortRead() {
reader.abort();
}
function errorHandler(evt) {
switch(evt.target.error.code) {
case evt.target.error.NOT_FOUND_ERR:
alert('File Not Found!');
break;
case evt.target.error.NOT_READABLE_ERR:
alert('File is not readable');
break;
case evt.target.error.ABORT_ERR:
break; // noop
default:
alert('An error occurred reading this file.');
};
}
function updateProgress(evt) {
// evt is an ProgressEvent.
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
// Increase the progress bar length.
if (percentLoaded < 100) {
progress.style.width = percentLoaded + '%';
progress.textContent = percentLoaded + '%';
}
}
}
function handleFileSelect(evt) {
// Reset progress indicator on new file selection.
progress.style.width = '0%';
progress.textContent = '0%';
reader = new FileReader();
reader.onerror = errorHandler;
reader.onprogress = updateProgress;
reader.onabort = function(e) {
alert('File read cancelled');
};
reader.onloadstart = function(e) {
document.getElementById('progress_bar').className = 'loading';
};
reader.onload = function(e) {
// Ensure that the progress bar displays 100% at the end.
progress.style.width = '100%';
progress.textContent = '100%';
setTimeout("document.getElementById('progress_bar').className='';", 2000);
}
// Read in the image file as a binary string.
reader.readAsBinaryString(evt.target.files[0]);
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);
</script>
4. Referencias
Especificación del API de archivos
Especificación de la interfaz FileReader
Especificación de la interfaz Blob
Especificación de la interfaz FileError
Especificación de ProgressEvent