No busques más en otras páginas ya que has llegado al sitio perfecto, tenemos la solución que buscas pero sin complicarte.
Solución:
[Edit]
Como se señaló en los comentarios anteriores, aunque todavía se encuentran en algunas implementaciones de UA, readAsBinaryString
El método no llegó a las especificaciones y no debe usarse en producción. En su lugar, use readAsArrayBuffer
y recorrerlo buffer
para recuperar el binario string :
document.querySelector('input').addEventListener('change', function()
var reader = new FileReader();
reader.onload = function()
var arrayBuffer = this.result,
array = new Uint8Array(arrayBuffer),
binaryString = String.fromCharCode.apply(null, array);
console.log(binaryString);
reader.readAsArrayBuffer(this.files[0]);
, false);
Para una forma más robusta de convertir su arrayBuffer en binario string, puede consultar esta respuesta.
[old answer] (modificado)
Sí, la API de archivos proporciona una forma de convertir su archivo, en el a un binario string, gracias al FileReader Object y su método
readAsBinaryString
.
[But don’t use it in production !]
document.querySelector('input').addEventListener('change', function()
var reader = new FileReader();
reader.onload = function()
var binaryString = this.result;
document.querySelector('#result').innerHTML = binaryString;
reader.readAsBinaryString(this.files[0]);
, false);
Si quieres un array búfer, entonces puede usar el readAsArrayBuffer()
método:
document.querySelector('input').addEventListener('change', function()
var reader = new FileReader();
reader.onload = function()
var arrayBuffer = this.result;
console.log(arrayBuffer);
document.querySelector('#result').innerHTML = arrayBuffer + ' '+arrayBuffer.byteLength;
reader.readAsArrayBuffer(this.files[0]);
, false);
$(document).ready(function()
(function (document)
var input = document.getElementById("files"),
output = document.getElementById("result"),
fileData; // We need fileData to be visible to getBuffer.
// Eventhandler for file input.
function openfile(evt)
var files = input.files;
// Pass the file to the blob, not the input[0].
fileData = new Blob([files[0]]);
// Pass getBuffer to promise.
var promise = new Promise(getBuffer);
// Wait for promise to be resolved, or log error.
promise.then(function(data)
// Here you can pass the bytes to another function.
output.innerHTML = data.toString();
console.log(data);
).catch(function(err)
console.log('Error: ',err);
);
/*
Create a function which will be passed to the promise
and resolve it when FileReader has finished loading the file.
*/
function getBuffer(resolve)
var reader = new FileReader();
reader.readAsArrayBuffer(fileData);
reader.onload = function()
var arrayBuffer = reader.result
var bytes = new Uint8Array(arrayBuffer);
resolve(bytes);
// Eventlistener for file input.
input.addEventListener('change', openfile, false);
(document));
);
Esta es una publicación larga, pero estaba cansado de todos estos ejemplos que no funcionaban para mí porque usaban objetos Promise o un error this
que tiene un significado diferente cuando estás usando Reactjs. Mi implementación estaba usando DropZone con reactjs, y obtuve los bytes usando un marco similar al que se publica en este sitio siguiente, cuando nada más de arriba funcionaría: https://www.mokuji.me/article/drop-upload- tutorial-1. Había 2 keys, para mi:
- Debe obtener los bytes del objeto de evento, utilizando y durante la función de carga de FileReader.
-
Probé varias combinaciones, pero al final, lo que funcionó fue:
const bytes = e.target.result.split('base64,')[1];
Dónde e
es el evento. Reaccionar requiere const
, podrías usar var
en JavaScript simple. Pero eso me dio el byte codificado en base64 string.
Así que solo voy a incluir las líneas aplicables para integrar esto como si estuvieras usando React, porque así es como lo estaba construyendo, pero intenta también generalizar esto y agregar comentarios cuando sea necesario, para que sea aplicable a un Javascript de vainilla implementación: advertí que no lo usé así en una construcción de este tipo para probarlo.
Estos serían sus enlaces en la parte superior, en su constructor, en un marco de React (no relevante para una implementación de Javascript de vainilla):
this.uploadFile = this.uploadFile.bind(this);
this.processFile = this.processFile.bind(this);
this.errorHandler = this.errorHandler.bind(this);
this.progressHandler = this.progressHandler.bind(this);
Y tendrías onDrop=this.uploadFile
en su elemento DropZone. Si estaba haciendo esto sin React, esto es el equivalente a agregar el controlador de eventos onclick que desea ejecutar cuando hace clic en el botón “Cargar archivo”.
Luego, la función (líneas aplicables … dejaré de lado mi restablecimiento de mi indicador de progreso de carga, etc.):
uploadFile(event){
// This is for React, only
this.setState(
files: event,
);
console.log('File count: ' + this.state.files.length);
// You might check that the "event" has a file & assign it like this
// in vanilla Javascript:
// var files = event.target.files;
// if (!files && files.length > 0)
// files = (event.dataTransfer ? event.dataTransfer.files :
// event.originalEvent.dataTransfer.files);
// You cannot use "files" as a variable in React, however:
const in_files = this.state.files;
// iterate, if files length > 0
if (in_files.length > 0)
for (let i = 0; i < in_files.length; i++)
// use this, instead, for vanilla JS:
// for (var i = 0; i < files.length; i++)
const a = i + 1;
console.log('in loop, pass: ' + a);
const f = in_files[i]; // or just files[i] in vanilla JS
const reader = new FileReader();
reader.onerror = this.errorHandler;
reader.onprogress = this.progressHandler;
reader.onload = this.processFile(f);
reader.readAsDataURL(f);
Había esta pregunta sobre esa sintaxis, para Vanilla JS, sobre cómo obtener ese objeto de archivo:
Carga de JavaScript / HTML5 / jQuery con la función de arrastrar y soltar: "Error de tipo no detectado: no se pueden leer los 'archivos' de propiedad indefinidos"
Tenga en cuenta que DropZone de React ya colocará el objeto File en this.state.files
para ti, siempre y cuando añadas files: [],
para usted this.state = ....
en su constructor. Agregué la sintaxis de una respuesta en esa publicación sobre cómo obtener su objeto File. Debería funcionar, o hay otras publicaciones que pueden ayudar. Pero todo lo que me dijo Q / A fue cómo obtener el File
objeto, no los datos de blob en sí. E incluso si lo hiciera fileData = new Blob([files[0]]);
como en la respuesta de sebu, que no incluía var
con él por alguna razón, no me dijo cómo leer el contenido de ese blob y cómo hacerlo sin un objeto Promise. Ahí es donde entró FileReader, aunque lo intenté y descubrí que no podía usar su readAsArrayBuffer
en cualquier caso.
Tendrá que tener las otras funciones que acompañan a esta construcción, una para manejar onerror
, uno para onprogress
(ambos se muestran más abajo), y luego el principal, onload
, que realmente hace el trabajo una vez que un método en reader
se invoca en esa última línea. Básicamente estás pasando tu event.dataTransfer.files[0]
directamente en eso onload
función, por lo que puedo decir.
Entonces el onload
el método llama a mi processFile()
función (solo líneas aplicables):
processFile(theFile)
return function(e)
const bytes = e.target.result.split('base64,')[1];
Y bytes
debe tener los bytes base64.
Funciones adicionales:
errorHandler(e)
switch (e.target.error.code)
case e.target.error.NOT_FOUND_ERR:
alert('File not found.');
break;
case e.target.error.NOT_READABLE_ERR:
alert('File is not readable.');
break;
case e.target.error.ABORT_ERR:
break; // no operation
default:
alert('An error occurred reading this file.');
break;
progressHandler(e)
if (e.lengthComputable)
const loaded = Math.round((e.loaded / e.total) * 100);
let zeros = '';
// Percent loaded in string
if (loaded >= 0 && loaded < 10)
zeros = '00';
else if (loaded < 100)
zeros = '0';
// Display progress in 3-digits and increase bar length
document.getElementById("progress").textContent = zeros + loaded.toString();
document.getElementById("progressBar").style.width = loaded + '%';
Y marcado de indicador de progreso aplicable:
000%
Y CSS:
.progressBar
background-color: rgba(255, 255, 255, .1);
width: 100%;
height: 26px;
#progressBar
background-color: rgba(87, 184, 208, .5);
content: '';
width: 0;
height: 26px;
EPÍLOGO:
Dentro processFile()
, por alguna razón, no pude agregar bytes
a una variable que tallé en this.state
. Entonces, en cambio, lo configuré directamente en la variable, attachments
, que estaba en mi objeto JSON, RequestForm
- el mismo objeto que mi this.state
estaba usando. attachments
es un array para poder enviar varios archivos. Fue así:
const fileArray = [];
// Collect any existing attachments
if (RequestForm.state.attachments.length > 0)
for (let i=0; i < RequestForm.state.attachments.length; i++)
fileArray.push(RequestForm.state.attachments[i]);
// Add the new one to this.state
fileArray.push(bytes);
// Update the state
RequestForm.setState(
attachments: fileArray,
);
Entonces, porque this.state
ya contenido RequestForm
:
this.stores = [
RequestForm,
]
Podría hacer referencia a él como this.state.attachments
de ahí en adelante. Función de reacción que no se aplica en Vanilla JS. Sin embargo, podría crear una construcción similar en JavaScript simple con una variable global y, en consecuencia, mucho más fácil:
var fileArray = new Array(); // place at the top, before any functions
// Within your processFile():
var newFileArray = [];
if (fileArray.length > 0)
for (var i=0; i < fileArray.length; i++)
newFileArray.push(fileArray[i]);
// Add the new one
newFileArray.push(bytes);
// Now update the global variable
fileArray = newFileArray;
Entonces siempre solo haces referencia fileArray
, enumerarlo para cualquier cadena de bytes de archivo, por ejemplo var myBytes = fileArray[0];
para el primer archivo.
Nos puedes sostener nuestra investigación exponiendo un comentario y dejando una puntuación te lo agradecemos.