2015-07-23 26 views
7

Sto provando a scrivere un file uploader per il framework Meteor. Il principio è dividere il file sul client da un ArrayBuffer in piccoli pacchetti di 4096 bit che vengono inviati al server attraverso un metodo Meteor.method.Come scrivere un file da un ArrayBuffer in JS

Il semplificata codice qui sotto è la parte del client che invia un pezzo al server, che viene ripetuto fino a compensare raggiunge data.byteLength:

// data is an ArrayBuffer 
var total = data.byteLength; 
var offset = 0; 

var upload = function() { 
    var length = 4096; // chunk size 

    // adjust the last chunk size 
    if (offset + length > total) { 
    length = total - offset; 
    } 

    // I am using Uint8Array to create the chunk 
    // because it can be passed to the Meteor.method natively 
    var chunk = new Uint8Array(data, offset, length); 

    if (offset < total) { 
    // Send the chunk to the server and tell it what file to append to 
    Meteor.call('uploadFileData', fileId, chunk, function (err, length) { 
     if (!err) { 
      offset += length; 
      upload(); 
     } 
    } 
    } 
}; 
upload(); // start uploading 

Il semplificata codice sotto è la parte sul server che riceve il blocco e lo scrive sul file system:

var fs = Npm.require('fs'); 
var Future = Npm.require('fibers/future'); 

Meteor.methods({ 
    uploadFileData: function(fileId, chunk) { 
    var fut = new Future(); 
    var path = '/uploads/' + fileId; 

    // I tried that with no success 
    chunk = String.fromCharCode.apply(null, chunk); 

    // how to write the chunk that is an Uint8Array to the disk ? 
    fs.appendFile(path, chunk, 'binary', function (err) { 
     if (err) { 
     fut.throw(err); 
     } else { 
     fut.return(chunk.length); 
     } 
    }); 
    return fut.wait(); 
    } 
}); 

Non sono riuscito a scrivere sul disco un file valido, in realtà il file viene salvato ma non riesco ad aprirlo, quando vedo il contenuto in un editor di testo, è simile al file originale (un jpg ad esempio) ma alcuni caratteri sono diversi, penso che potrebbe essere un problema di codifica in quanto la dimensione del file non è la stessa, ma non so come risolvere il problema ...

+1

è possibile passare un blob, invece? di solito escono nel nodo come buffer, che gestisce fs.AppendFile(). – dandavis

+1

@dandavis In realtà mi hai dato la metà della risposta, vedi la soluzione è stata semplice, grazie! –

risposta

8

Salvare il file è stato facile come creare un nuovo Buffer con il Uint8Array oggetto:

// chunk is the Uint8Array object 
fs.appendFile(path, new Buffer(chunk), function (err) { 
    if (err) { 
     fut.throw(err); 
    } else { 
     fut.return(chunk.length); 
    } 
}); 
1

volevo solo aggiungere che nel recente Meteor si potrebbe evitare alcuni callback diavolo async/await. Attendono anche lanciare e spingere l'errore fino a cliente

Meteor.methods({ 
    uploadFileData: async function(file_id, chunk) { 
    var path = 'somepath/' + file_id; // be careful with this, make sure to sanitize file_id 
    await fs.appendFile(path, new Buffer(chunk)); 
    return chunk.length; 
    } 
}); 
1

Sulla Karl.S answer, questo ha funzionato per me, al di fuori di qualsiasi quadro:

fs.appendFileSync(outfile, new Buffer(arrayBuffer));