javascript - ¿Cómo funciona FileReader.readAsText en HTML5 File API?
drag-and-drop textarea (2)
Escribí el siguiente código para verificar si el archivo cargado existe o no usando la API de archivo HTML5.
<input type="file" id="myfile">
<button type="button" onclick="addDoc()">Add Document</button>
<p id="DisplayText"></p>
El siguiente código JavaScript que se ha asignado es el siguiente:
function addDoc() {
var file=document.getElementById("myFile").files[0]; //for input type=file
var reader=new FileReader();
reader.onload = function(e) {}
reader.readAsText(file);
var error = reader.error;
var texte=reader.result;
document.getElementById("DisplayText").innerText=reader.result; /*<p id="DisplayText>*/
}
Después de examinar un archivo del sistema local, intenté eliminar el documento "examinado" de la carpeta antes de hacer clic en
addDoc()
.
Después de hacer clic en el botón, todavía podía ver
Filereader.result
no es nulo y podría mostrar todo el contenido.
¿Alguien puede explicar cómo funciona Filereader ? ¿Es que FileReader queda vinculado tan pronto como se navega por el archivo?
¿También podemos verificar si el sistema de atributo de solo
lectura
con
FileReader es
similar a Java
File.canread()
?
¿Podría alguien sugerir sobre esto? Tengo IE11 para probar el código.
El objeto FileReader permite que las aplicaciones web lean de forma asíncrona el contenido de los archivos (o memorias intermedias de datos sin procesar) almacenados en la computadora del usuario, utilizando objetos File o Blob para especificar el archivo o los datos a leer.
Los objetos de archivo se pueden obtener de un objeto FileList devuelto como resultado de que un usuario seleccione archivos usando el elemento, del objeto DataTransfer de una operación de arrastrar y soltar, o de la API mozGetAsFile () en un HTMLCanvasElement.
El método readAsText se usa para leer el contenido del Blob o Archivo especificado. Cuando se completa la operación de lectura, readyState se cambia a DONE, se activa el loadend y el atributo de resultado contiene el contenido del archivo como una cadena de texto.
Sintaxis
instanceOfFileReader.readAsText(blob[, encoding]);
Parámetros
Gota
El blob o archivo desde el que leer.
codificación opcional
Una cadena que especifica la codificación a usar para los datos devueltos. Por defecto, se supone UTF-8 si este parámetro no se especifica.
Para los metadatos sobre un archivo, podemos verificar el objeto Archivo
F
manera que: F tenga un estado de legibilidad de ABIERTO.
F se refiere a la secuencia de bytes de bytes.
F.size
se establece en el número total de bytes en bytes.
F.name
se establece en n.
F.type
se establece en t.
Nota: El tipo t de un archivo se considera un tipo MIME analizable si la cadena codificada en ASCII que representa el tipo de objeto del archivo, cuando se convierte en una secuencia de bytes, no regresa indefinida para el algoritmo de tipo MIME analizado [MIMESNIFF].
F.lastModified
se establece en d.
Vea más sobre compatibilidad del navegador y documentos detallados para FileReader , File y readAsText en MDN, también este borrador del W3C para FileApi
FileReader
evento de
load
FileReader
establece el valor
.result
forma asincrónica.
Para acceder al
.result
use
load
o
loadend
event.
Cuando se ha seleccionado un archivo en
<input type="file">
Choose File
o
Browse...
UI, eliminar el archivo en el sistema de archivos local no debería afectar el objeto
File
en
FileList
devuelto por la llamada
.files
.
Ver
2.9.2.
Objetos transferibles
,
6.7.3 La interfaz DataTransfer
.
4. La interfaz de blob y los datos binarios
Cada
Blob
debe tener un estado de instantánea interno, que debe establecerse inicialmente en el estado del almacenamiento subyacente, si existe dicho almacenamiento subyacente, y debe conservarse mediantestructured clone
. Se puede encontrar una definición normativa adicional delsnapshot state
de lasnapshot state
para losFile
.
2.9.8 Parche de mono para objetos Blob y FileList
Este parche de mono se eliminará a su debido tiempo. Ver w3c / FileAPI número 32 .
Blob
objetosBlob
soncloneable objects
.
El método interno [[
Clone
]] de cada objetoBlob
, dado targetRealm e ignorando la memoria, debe ejecutar estos pasos:Si esto está
closed
, arroje una"DataCloneError"
DOMException
"DataCloneError"
.Devuelve una nueva instancia de esto en targetRealm , correspondiente a los mismos datos subyacentes.
FileList
objetosFileList
son objetos clonables .El método interno de cada objeto
FileList
[[Clone]]
, dado targetRealm y memoria , debe ejecutar estos pasos:
Deje que la salida sea un nuevo objeto FileList en targetRealm .
Para cada archivo en este , agregue?
[StructuredClone][15](_file, targetRealm, memory_)
al final de la lista de objetosFile
de salida .Salida de retorno.
Selección de archivos o carpetas de solo lectura en los navegadores webkit y firefox
En Chrome, Chrome si el permiso de solo lectura se establece para el archivo en el sistema de archivos local y el usuario selecciona el archivo en el elemento
<input type="file">
, donde
FileReader
se usa para leer el archivo, se genera un error en
FileReader
, generado a partir del
progress
FileReader
evento.
Si una
Blob URL
se establece en el mismo objeto de archivo,
blob:
URL no devolverá el archivo de solo lectura cuando se solicite a la
Blob URL
.
Selección de carpeta donde el permiso de carpeta se establece en solo lectura
Cromo, cromo
En Chrome, el cromo donde se
webkitdirectory
atributo
webkitdirectory
y se selecciona la carpeta con permiso de solo lectura
FileList
.length
of
event.target.files
devuelto
0
;
event.target.files.webkitGetAsEntry()
no se llama,
"No file chosen"
se representa en
<input type="file">
shadowDOM
.
Cuando una carpeta se cae en
<input type="file">
o elemento donde se establece el atributo
.path
, el directorio
.name
y
.path
de la carpeta de solo lectura se muestra en
drop
event.dataTransfer
.
Cuando el usuario suelta el archivo o la carpeta en el elemento
<textarea>
, donde no se adjunta ningún evento de
drop
que se
beforeunload
evento de
beforeunload
y se muestra un indicador en la interfaz de usuario
Do you want to leave this site? Changes you made may not be saved. <Stay><Leave> // <buttons>
Firefox
En firefox versión 47.0b9 con el atributo
allowdirs
se establece en el elemento
<input type="file">
, donde el usuario hace clic en
"Choose folder.."
<input>
, la carpeta
.name
y
.path
de la carpeta principal están accesibles en
.then()
encadenado a
event.target.getFilesAndDirectories()
.
Los archivos o carpetas contenidos en la carpeta seleccionada no se devuelven al iterar recursivamente las entradas del
Directory
;
Se devuelve una cadena vacía.
Si el usuario hace clic en
"Choose file..."
<input>
y se selecciona una carpeta sin un conjunto de permisos de solo lectura, cuando se hace clic en la carpeta del administrador de archivos, se enumeran los archivos de la carpeta.
Cuando se selecciona una carpeta donde se configura el permiso de solo lectura, se muestra una notificación de
alert()
en la IU que se muestra
Could not read the contents of <directory name> Permission denied
Error, problema de seguridad
* sistema operativo nix
Cuando el usuario suelta la carpeta en el elemento
<textarea>
, donde no se adjunta ningún evento de
drop
, la ruta completa a la carpeta en el
file:
sistema de
file:
usuario
file:
protocolo queda expuesto.
Las rutas a los archivos contenidos dentro de la carpeta no se configuran también como
.value
;
p.ej,
"file:///home/user/Documents/Document/"
Cuando se
drop
un archivo en el elemento
<textarea>
, donde se adjunta el evento no
drop
, la ruta completa al archivo en el sistema de archivos del usuario se establece como
.value
de
<textarea>
;
es decir,
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.txt"
Si se seleccionan varios archivos y se sueltan en el elemento
<textarea>
, todas las rutas de archivos completas se establecen como
.value
de
<textarea>
, delineadas por el nuevo carácter de línea
/n
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue1.txt"
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue2.txt"
..
Donde se realiza un
XMLHttpRequest()
para la ruta del archivo y el error se registra en la
console
NS_ERROR_DOM_BAD_URI: Access to restricted URI denied
Cuando se establece como
.src
de un elemento
<img>
con
.crossOrigin
establecido en
"anonymous"
se llama al controlador de eventos de
error
img
En la llamada a
window.open()
con la ruta completa establecida en el primer parámetro
Error: Access to ''"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.png"'' from script denied
Especificación
4.10.5.1.18.
Estado de carga de archivo (
type=file
)
Por razones históricas, el
value
atributo IDL antepone el nombre del archivo con la cadena "C:/fakepath/
". Algunos agentes de usuario heredados en realidad incluían la ruta completa (que era una vulnerabilidad de seguridad). Como resultado de esto, obtener el nombre del archivo del atributo IDL devalue
de una manera compatible con versiones anteriores no es trivial.
4.10.5.4.
API de elementos
<input>
comunes
nombre del archivo
Al obtener, debe devolver la cadena "C: / fakepath /" seguida del nombre del primer archivo en la lista de
selected files
, si corresponde, o la cadena vacía si la lista está vacía. En la configuración, si el nuevo valor es la cadena vacía, debe vaciar la lista deselected files
; de lo contrario, debe arrojar unaInvalidStateError
"DOMException
".NOTA: Este requisito de "ruta falsa" es un triste accidente de la historia. Consulte el ejemplo en la sección Estado de carga de archivos para obtener más información.
NOTA: Dado
path components
no están permitidos en los nombres de archivo en la lista deselected files
, "/fakepath/
" no puede confundirse con un componente de ruta.
4.10.5.1.18.
Estado de carga de archivo (
type=file
)
Componentes de la ruta
Cuando el atributo de
type
de un elemento<input>
está en el estado deFile Upload
, se aplican las reglas de esta sección.El elemento
<input>
represents
una lista deselected files
, cada archivo consta de un nombre de archivo, un tipo de archivo y un cuerpo de archivo (el contenido del archivo).Los nombres de archivo no deben contener
path components
, incluso en el caso de que un usuario haya seleccionado una jerarquía de directorio completa o varios archivos con el mismo nombre de diferentes directorios. Los componentes de ruta , a los efectos del estado deFile Upload
, son aquellas partes de los nombres de archivo que están separadas por caracteres U + 005C REVERSE SOLIDUS character ().
Informe de error https://bugzilla.mozilla.org/show_bug.cgi?id=1311823
Colocar el archivo en <textarea> en el URI de datos
Siguiente comentario de Neal Deakin en el informe de error
Creo que los pasos mencionados son:
- Datos abiertos: texto / html,
- Arrastre un archivo desde el escritorio al área de texto
Puedo reproducir esto en Linux, pero no en Windows o Mac.
La corazonada de arriba es correcta; Linux también incluye los datos como una url y texto sin formato.
archivos caídos en los
data:
data URI
prototcol en firefox y cromo, cromo
data:text/html,<textarea></textarea>
Firefox
El nombre de ruta completo del archivo o carpeta establecido como
.value
de
<textarea>
.
Cromo, cromo
Al soltar el archivo en
data URI
tiene solo un elemento de área de
textarea
en Chrome, el cromo reemplaza el
data URI
con la ruta del archivo en la barra de direcciones y carga el archivo en la misma pestaña, reemplazando el
data URI
con el contenido del archivo.
plnkr http://plnkr.co/edit/ZfAGEAiyLLq8rGXD2ShE?p=preview
html
,
javascript
para reproducir el problema descrito anteriormente
<!DOCTYPE html>
<html>
<head>
<style>
body {
height: 400px;
}
textarea {
width: 95%;
height: inherit;
}
</style>
<script>
window.onload = function() {
var button = document.querySelector("#myfile + button");
var input = document.getElementById("myfile");
var display = document.getElementById("DisplayText");
var text = null;
function readFullPathToFileOnUserFileSystem(e) {
var path = e.target.value;
console.log(path);
var w = window.open(path, "_blank");
var img = new Image;
img.crossOrigin = "anonymous";
img.onload = function() {
document.body.appendChild(this);
}
img.onerror = function(err) {
console.log("img error", err.message)
}
img.src = path;
var request = new XMLHttpRequest();
request.open("GET", path.trim(), true);
request.onload = function() {
console.log(this.responseText)
}
request.error = function(err) {
console.log(err.message)
}
request.send();
}
display.addEventListener("input", readFullPathToFileOnUserFileSystem);
input.addEventListener("change", addDoc);
input.addEventListener("progress", function(event) {
console.log("progress", event)
});
button.addEventListener("click", handleText)
function addDoc(event) {
var mozResult = [];
function mozReadDirectories(entries, path) {
console.log("dir", entries, path);
return [].reduce.call(entries, function(promise, entry) {
return promise.then(function() {
console.log("entry", entry);
return Promise.resolve(entry.getFilesAndDirectories() || entry)
.then(function(dir) {
console.log("dir getFilesAndDirectories", dir)
return dir
})
})
}, Promise.resolve())
.catch(function(err) {
console.log(err, err.message)
})
.then(function(items) {
console.log("items", items);
var dir = items.filter(function(folder) {
return folder instanceof Directory
});
var files = items.filter(function(file) {
return file instanceof File
});
if (files.length) {
console.log("files:", files, path);
mozResult = mozResult.concat.apply(mozResult, files);
}
if (dir.length) {
console.log(dir, dir[0] instanceof Directory, dir[0]);
return mozReadDirectories(dir, dir[0].path || path);
} else {
if (!dir.length) {
return Promise.resolve(mozResult).then(function(complete) {
return complete
})
}
}
})
.catch(function(err) {
console.log(err)
})
};
console.log("files", event.target.files);
if ("getFilesAndDirectories" in event.target) {
return (event.type === "drop" ? event.dataTransfer : event.target)
.getFilesAndDirectories()
.then(function(dir) {
if (dir[0] instanceof Directory) {
console.log(dir)
return mozReadDirectories(dir, dir[0].path || path)
.then(function(complete) {
console.log("complete:", complete);
event.target.value = null;
});
} else {
if (dir[0] instanceof File && dir[0].size > 0) {
return Promise.resolve(dir)
.then(function(complete) {
console.log("complete:", complete);
})
} else {
if (dir[0].size == 0) {
throw new Error("could not process ''" + dir[0].name + "'' directory" + " at drop event at firefox, upload folders at ''Choose folder...'' input");
}
}
}
}).catch(function(err) {
console.log(err)
})
}
var reader = new FileReader();
reader.onload = function(e) {
text = reader.result;
console.log("FileReader.result", text);
button.removeAttribute("disabled");
}
reader.onerror = function(err) {
console.log(err, err.loaded, err.loaded === 0, file);
button.removeAttribute("disabled");
}
reader.onprogress = function(e) {
console.log(e, e.lengthComputable, e.loaded, e.total);
}
reader.readAsArrayBuffer(file);
}
function handleText() {
// do stuff with `text`: `reader.result` from `addDoc`
display.textContent = text;
button.setAttribute("disabled", "disabled");
// set `text` to `null` if not needed or referenced again
text = null;
}
}
</script>
</head>
<body>
<input type="file" id="myfile" webkitdirectory directory allowdirs>
<button type="button" disabled>Add Document</button>
<br>
<br>
<textarea id="DisplayText"></textarea>
</body>
</html>
plnkr http://plnkr.co/edit/8Ovw3IlYKI8BYsLhzV88?p=preview
Puede usar el evento de
change
adjunto al elemento
#myfile
para manejar la acción de selección de archivos por usuario.
Sustituya el elemento
<textarea>
por el elemento
<p>
para mostrar el resultado del evento de
load
de la llamada
.readAsText()
.
Para mostrar
.result
de
FileReader
al
click
en el elemento del
button
, establezca el
text
variable en
reader.result
dentro del evento de
load
de
FileReader
al
click
evento al configurar el
button
.textContent
del elemento
#DisplayText
para hacer referencia a variables que establecieron anteriormente
reader.result
.
<!DOCTYPE html>
<html>
<style>
body {
height: 400px;
}
textarea {
width:95%;
height: inherit;
}
</style>
<head>
<script>
window.onload = function() {
var button = document.querySelector("#myfile + button");
var input = document.getElementById("myfile");
var display = document.getElementById("DisplayText");
var text = null;
input.addEventListener("change", addDoc);
button.addEventListener("click", handleText)
function addDoc(event) {
var file = this.files[0]
var reader = new FileReader();
reader.onload = function(e) {
text = reader.result;
button.removeAttribute("disabled");
}
reader.onerror = function(err) {
console.log(err, err.loaded
, err.loaded === 0
, file);
button.removeAttribute("disabled");
}
reader.readAsText(event.target.files[0]);
}
function handleText() {
// do stuff with `text`: `reader.result` from `addDoc`
display.textContent = text;
button.setAttribute("disabled", "disabled");
// set `text` to `null` if not needed or referenced again
text = null;
}
}
</script>
</head>
<body>
<input type="file" id="myfile" accept="text/*">
<button type="button" disabled>Add Document</button><br><br>
<textarea id="DisplayText"></textarea>
</body>
</html>