Saltar al contenido

Obteniendo byte array a través del tipo de entrada = archivo

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:

  1. Debe obtener los bytes del objeto de evento, utilizando y durante la función de carga de FileReader.
  2. 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.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4.5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *