2012-09-27 10 views
6

Sto cercando di creare un uploader html per file di grandi dimensioni utilizzando HTML5 e Web Workers. Atm carica lentamente ma consuma molta memoria. Penso che stia trasferendo l'intero file alla memoria quando lo aggiunge al modulo. Heres il codice: jswebworker.js:Caricamento file JavaScript Web Work

/*importScripts('webworkerFormData.js');*/ 

(function() { 
// Export variable to the global scope 
(this == undefined ? self : this)['FormData'] = FormData; 

var ___send$rw = XMLHttpRequest.prototype.send; 
XMLHttpRequest.prototype['send'] = function(data) { 
    if (data instanceof FormData) { 
     if (!data.__endedMultipart) data.__append('--' + data.boundary + '--\r\n'); 
     data.__endedMultipart = true; 
     this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + data.boundary); 
     data = new Uint8Array(data.data).buffer; 
    } 
    // Invoke original XHR.send 
    return ___send$rw.call(this, data); 
}; 

function FormData() { 
    // Force a Constructor 
    if (!(this instanceof FormData)) return new FormData(); 
    // Generate a random boundary - This must be unique with respect to the form's contents. 
    this.boundary = '------RWWorkerFormDataBoundary' + Math.random().toString(36); 
    var internal_data = this.data = []; 
    /** 
    * Internal method. 
    * @param inp String | ArrayBuffer | Uint8Array Input 
    */ 
    this.__append = function(inp) { 
     var i=0, len; 
     if (typeof inp === 'string') { 
      for (len=inp.length; i<len; i++) 
       internal_data.push(inp.charCodeAt(i) & 0xff); 
     } else if (inp && inp.byteLength) {/*If ArrayBuffer or typed array */ 
      if (!('byteOffset' in inp)) /* If ArrayBuffer, wrap in view */ 
       inp = new Uint8Array(inp); 
      for (len=inp.byteLength; i<len; i++) 
       internal_data.push(inp[i] & 0xff); 
     } 
    }; 
} 
/** 
* @param name  String         Key name 
* @param value String|Blob|File|Uint8Array|ArrayBuffer Value 
* @param filename String         Optional File name (when value is not a string). 
**/ 
FormData.prototype['append'] = function(name, value, filename) { 
    if (this.__endedMultipart) { 
     // Truncate the closing boundary 
     this.data.length -= this.boundary.length + 6; 
     this.__endedMultipart = false; 
    } 
    var valueType = Object.prototype.toString.call(value), 
     part = '--' + this.boundary + '\r\n' + 
      'Content-Disposition: form-data; name="' + name + '"'; 

    if (/^\[object (?:Blob|File)(?:Constructor)?\]$/.test(valueType)) { 

     return this.append(name, 
         new Uint8Array(new FileReaderSync().readAsArrayBuffer(value)), 
         filename || value.name); 
    } else if (/^\[object (?:Uint8Array|ArrayBuffer)(?:Constructor)?\]$/.test(valueType)) { 
     part += '; filename="'+ (filename || 'blob').replace(/"/g,'%22') +'"\r\n'; 
     part += 'Content-Type: application/octet-stream\r\n\r\n'; 
     this.__append(part); 
     this.__append(value); 
     part = '\r\n'; 
    } else { 
     part += '\r\n\r\n' + value + '\r\n'; 
    } 
    this.__append(part); 
}; 
})(); 

movies = []; 
var timeStarted = 0; 
uploadingVar = false; 
const BYTES_PER_CHUNK = 64 * 1024 * 1024; 

function toTitleCase(str) 
{ 
return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1);}); 
} 

function newUpload(blobOrFile, moviename, filename, i, fileType, sizeFile) { 
var xhr = new XMLHttpRequest(); 
path = '/moviehtml/newmupload.php?  moviename='+escape(moviename)+'&filename='+escape(filename)+'&num='+escape(i); 
xhr.open('POST', path, false); 
self.postMessage(blobOrFile.size); 
var fd = new FormData(); 
//xhr.setRequestHeader('Content-Type', fileType) 
//blobOrFile2 = FileReaderSync.readAsArrayBuffer(blobOrFile); 
fd.append("files1", blobOrFile); 
//fd.append("moviename", moviename); 
//fd.append("filename", filename); 
//fd.append("num",i); 

seconds = new Date()/1000; 
xhr.send(fd); 
self.postMessage(xhr.responseText) 
self.postMessage({'type':'partial','done':i*BYTES_PER_CHUNK, 'started':timeStarted, 'total':sizeFile}); 
var finish = Date()/1000; 
if (finish >= (seconds+100)){ 
    return false; 
} 
return true; 

} 
function newFileUpload(file, movieName, fileType, filename, exten){ 
if (movieName == movieName.match(/[a-zA-Z0-9\. \:]+/)){ 
    timeStarted = new Date().getTime(); 

var blob = file;// this.files[0]; 
//var filename = blob.name; 
var moviename = toTitleCase(movieName); 
// 1MB chunk sizes. 
const SIZE = blob.size; 
//alert(SIZE + ' '+document.getElementById('fileToUpload').files[0].size) 
var start = 0; 
var end = BYTES_PER_CHUNK; 
//alert(SIZE/BYTES_PER_CHUNK) 
var i = 1; 
while(start < SIZE) { 
    wow = newUpload(blob.slice(start, end), moviename, filename, i, fileType, SIZE); 

    start = end; 
    end = start + BYTES_PER_CHUNK; 
    i++; 
} 
var xhr = new XMLHttpRequest(); 
var fd2 = new FormData(); 
typeFile = filename.split('.').pop() 
fd2.append("type", blob.type); 
fd2.append("exten", typeFile); 
fd2.append("moviename", moviename); 
xhr.open('POST', '/moviehtml/finishedupload.php', false); 
xhr.send(fd2); 
} 
} 
function process(){ 
uploadingVar = true; 
while(movies.length > 0) { 

    upMovie = movies.pop(); 
    var file = upMovie[0]; 
    var movieName = upMovie[1]; 
    var fileType = upMovie[2]; 
    var filename = upMovie[3]; 
    var exten = upMovie[4]; 
    self.postMessage({'type':'start','size':file.size, 'name':movieName}); 

    newFileUpload(file, movieName, fileType, filename, exten); 
    self.postMessage({'type':'finish','name':movieName}) 
    self.postMessage(movieName + " Uploaded Succesfully"); 
} 
uploadingVar = false; 
} 

self.addEventListener('message', function(e) { 
movies.push(e.data); 
if (!uploadingVar){ 
process(); 

} 
}, false); 

La mia funzione che lo chiama:

var worker = new Worker('jswebworker.js'); 
function testUpload(){ 
//newFileUpload(); 
var file = document.getElementById('fileToUpload').files[0]; 
worker.postMessage([file,toTitleCase(document.getElementById('movieName').value),  file.type, file.name, file.name.split('.').pop()]); 

} 

Questa è la pagina web per un media server per il mio appartamento. Spero che ci sia un modo per creare un blob senza caricare tutto l'originale nella memoria. Grazie per qualsiasi aiuto, Nick

+0

Dove è possibile trovare una soluzione? – Hadesara

+0

Perché non fornite un codice più semplice? Credo che più persone lo leggeranno davvero se lo farai. – stevemao

risposta

1

penso che this libreria (qui è la pagina GitHub per resumable.js pure) possono essere già facendo quello che si sta tentando troppo compiere. Dal momento che non so quanto sono grandi i file che stai caricando per il caricamento, non posso fornire alcuna comprensione per quanto riguarda i benchmark. Spero che questo ti aiuti.

Problemi correlati