2014-10-15 17 views
9

All'interno della mia app Cordova, sto scaricando file arbitrari come immagini o file video. Questo viene fatto con il plugin di trasferimento file di Cordova e l'intestazione "Range", perché ho bisogno di scaricare i file in parti.Unione di più parti di un file in Cordova

Il mio problema è che voglio unire indietro i vari piccoli "byte" -Fili insieme nel file originale in cui una volta dove si utilizza quel file. Ogni volta che cerco di leggere le parti risultanti come binaryString tramite FileReader e di scriverle insieme in un nuovo file, il file finisce molto più delle parti del file originale e il file risultante è inutilizzabile.

Qualsiasi aiuto è apprezzato.

Ecco il mio codice fino ad ora (lungo e brutto): Codice

document.addEventListener('deviceready', deviceready, false); 

var App; 

var finishedFileUrl = ""; 

var async = { 
    sequence: function(items, callback) {  
     var def = $.Deferred(), 
     deferrers = [$.Deferred()]; 

     for(var i = 0; i < items.length; i++) { 
      (function (n) {  
       deferrers[n + 1] = $.Deferred(); 
       deferrers[n].always(function() { 
        callback(items[n], deferrers[n + 1]); 
       }); 
      })(i); 
     } 
     deferrers[items.length].always(function() { 
      def.resolve(); 
     });   
     deferrers[0].resolve(); 

     return def.promise(); 
    } 
} 

var aSmallImageArray = [ 
'' // Put URL to JPG accessible with Range Header Request here 
]; 

var aByteSizeImageArray = []; 

function formatDownloadArray(fileSize) { 
    for(var j = 1000; j <= fileSize; j += 1000) { 
     aByteSizeImageArray.push(j); 
    } 
    aByteSizeImageArray.push(j); 
} 

function deviceready() { 
    console.log('dv ready'); 

    function registerHandlers() { 
     App = new DownloadApp(); 
     formatDownloadArray(XXXXX);  // XXXXX should be size of JPG in bytes 
     document.getElementById("startDl").onclick = function() { 
      var that = this; 
      console.log("load button clicked"); 
      var folderName = "testimagefolder"; 

      // sequence call 
      async.sequence(aByteSizeImageArray, function(currentBytes, iter) { 
       var filePath = aSmallImageArray[0]; 
       var fileName = aSmallImageArray[0].substr(52,99) + currentBytes; 
       console.log(filePath); 
       console.log(fileName); 
       console.log("Starting with: " + fileName); 
       var uri = encodeURI(filePath); 
       var folderName = "testimagefolder"; 
       document.getElementById("statusPlace").innerHTML = "<br/>Loading: " + uri; 
       App.load(currentBytes, uri, folderName, fileName, 
        function progress (percentage) { 
         document.getElementById("statusPlace").innerHTML = "<br/>" + percentage + "%"; 
        }, 
        function success (entry) { 
         console.log("Entry: " + entry); 
         document.getElementById("statusPlace").innerHTML = "<br/>Image saved to: " + App.filedir; 
         console.log("DownloadApp.filedir: " + App.filedir); 
         iter.resolve(); 
        }, 
        function error() { 
         document.getElementById("statusPlace").innerHTML = "<br/>Failed load image: " + uri; 
         iter.resolve(); 
        } 
       );    
      }).then(function afterAsync() { 
       console.log("ASYNC DONE"); 
       var ohNoItFailed = function ohNoItFailed (exeperro) { 
        console.log(exeperro); 
       } 
       // now we merge the fileparts into one file to show it 
       window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) { 
        FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) { 
         Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function itSuccessedAgain (fileEntry) { 
          finishedFileUrl = fileEntry.toURL(); 
          var directoryReader = Directory.createReader(); 
          var allFiles = directoryReader.readEntries(function succesReadDir (fileEntries) { 
           async.sequence(fileEntries, function(currentFile, iterThis) { 
            currentFile.file(function (theActualFile) { 
             var myFileReader = new FileReader(); 
             myFileReader.onload = function (content) { 
              console.log('FileReader onload event fired!'); 
              console.log('File Content should be: ' + content.target.result); 
              fileEntry.createWriter(
              function mergeImage (writer) { 
               writer.onwrite = function (evnt) { 
                console.log("Writing successful!"); 
                iterThis.resolve(); 
               } 
               writer.seek(writer.length); 
               writer.write(content.target.result); 
              }, ohNoItFailed); 
             }; 
             myFileReader.readAsBinaryString(theActualFile); 
            }, ohNoItFailed); 
           }).then(function afterAsyncTwo() { 
            console.log("NOW THE IMAGE SHOULD BE TAKEN FROM THIS PATH: " + finishedFileUrl); 

            //window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (FileSystem) { 
             //FileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, function itSuccessed (Directory) { 
              //Directory.getFile(aSmallImageArray[0].substr(52,99), {create: true, exclusive: false}, function  itSuccessedAgain (fileEntry) {  
               //fileEntry.createWriter( 

             document.getElementById("image_here").src = finishedFileUrl;  
           });  
          }, ohNoItFailed);        
         }, ohNoItFailed);  
        }, ohNoItFailed);  
       }, ohNoItFailed);      
      });  
     };  
    }  
    registerHandlers();  
}  

var DownloadApp = function() {} 

DownloadApp.prototype = { 
    filedir: "", 
    load: function(currentBytes, uri, folderName, fileName, progress, success, fail) { 
     var that = this; 
     that.progress = progress; 
     that.success = success; 
     that.fail = fail; 
     filePath = ""; 

     that.getFilesystem(
       function(fileSystem) { 
        console.log("GotFS"); 
        that.getFolder(fileSystem, folderName, function(folder) { 
         filePath = folder.toURL() + fileName; 
         console.log("FILEPATH: " + filePath); 
         console.log("URI: " + uri); 
         that.transferFile(currentBytes, uri, filePath, progress, success, fail); 
        }, function(error) { 
         console.log("Failed to get folder: " + error.code); 
         typeof that.fail === 'function' && that.fail(error); 
        }); 
       }, 
       function(error) { 
        console.log("Failed to get filesystem: " + error.code); 
        typeof that.fail === 'function' && that.fail(error); 
       } 
     ); 
    }, 

    getFilesystem: function (success, fail) { 
     window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; 
     window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, success, fail); 
    }, 

    getFolder: function (fileSystem, folderName, success, fail) { 
     fileSystem.root.getDirectory(folderName, {create: true, exclusive: false}, success, fail) 
    }, 

    transferFile: function (currentBytes, uri, filePath, progress, success, fail) { 
     var that = this; 
     that.progress = progress; 
     that.success = success; 
     that.fail = fail; 
     console.log("here we go"); 
     console.log("filePath before Request: " + filePath); 

     var previousBytes = currentBytes - 1000; 

     var transfer = new FileTransfer(); 
     transfer.onprogress = function(progressEvent) { 
      if (progressEvent.lengthComputable) { 
       var perc = Math.floor(progressEvent.loaded/progressEvent.total * 100); 
       typeof that.progress === 'function' && that.progress(perc); // progression on scale 0..100 (percentage) as number 
      } else { 
      } 
     }; 

     transfer.download(
      uri, 
      filePath, 
      function success (entry) { 
       console.log("File saved to: " + entry.toURL()); 
       typeof that.success === 'function' && that.success(entry); 
      }, 
      function errorProblem(error) { 
       console.log("An error has occurred: Code = " + error.code); 
       console.log("download error source " + error.source); 
       console.log("download error target " + error.target); 
       console.log("download error code " + error.code); 
       typeof that.fail === 'function' && that.fail(error); 
      }, 
      true, 
      { 
       headers: { 
        "Range": "bytes=" + previousBytes + "-" + currentBytes 
       } 
      } 
     ); 
    } 
} 

asincrono per StackOverflow-utente: Paul Facklam -> Grazie mille!

+0

Potete aggiungere ulteriori dettagli e commenti sul codice? Sembra che tu stia cercando di caricare file 1000 byte alla volta, ma ci sono alcuni numeri magici che non sono chiari ('1000',' 52', '99'). Se i pezzi risultanti si stanno assemblando più del previsto, è possibile che il file sia stato scritto come ASCII/caratteri invece che come dati binari? Hai dimenticato di omettere le intestazioni di risposta? (se del caso, non sono sicuro) Suggerimento: prova a scaricare un file di piccole dimensioni che ha solo un paio di pezzi e usa un editor esadecimale per confrontare i pezzi salvati con il file originale dal server. Diamine, prova con un file di testo in chiaro. – nothingisnecessary

+0

I "numeri magici" sono usati per estrarre il nome del file dal primo elemento dell'array (52,99), il 1000, come si suppone correttamente, corrisponde alle parti da 1000 byte che voglio scaricare. Ho già provato con un file più piccolo e se guardo i contenuti non sono certamente binari, ma caratteri bytecode. Posso pubblicare un esempio di un pezzo di quel file, se ciò sarebbe di aiuto. – plocks

risposta

1

L'utilizzo di readAsArrayBuffer() invece di readAsBinaryString() ha fatto il trucco!

Così, invece di:

myFileReader.readAsBinaryString(theActualFile); 

ho fatto:

myFileReader.readAsBinaryArray(theActualFile); 

e il file di immagine risultante è utilizzabile.

1

è possibile creare un BLOB da altri BLOB, come quelli su cui si usa FileReader ora. (File() s sono Blobs)

// put three blobs into a fourth: 
var b=new Blob([new Blob(["hello"]), new Blob([" "]), new Blob(["world"])]); 

// verify the blob has the data we expect: 
var fr=new FileReader(); 
fr.onload=function(){alert(this.result);}; 
fr.readAsBinaryString(b); // shows: "hello world" 

il sapore binaryString viene qui utilizzato per mostrare come queste stringhe di ordine inferiore accumulano, ma l'attuale nuova istanza blob dovrebbero avere tutte le orig (arbitraria) byte dall'originale BLOB, anche se non sono composti da stringhe semplici ...

+0

Lo testerò. Grazie. – plocks

+0

Ok, l'ho provato e non funziona per me. Non produce ancora un file immagine visualizzabile. – plocks

+0

@DevanLoper: senza vedere il codice aggiornato, non posso dire perché non funziona, ma ho verificato che i dati binari possono essere ritagliati e riassemblati usando l'approccio sopra: http://jsfiddle.net/ox0rgmvc/ 1/ – dandavis