2011-12-04 16 views
9

Fondamentalmente lavorerò con file XML di grandi dimensioni (circa 20 - 50 MB). Questi file devono essere caricati su un server.Compressione file prima del caricamento sul lato client

So che non è possibile toccare i file con javascript né implementare la compressione HTTP sul lato client.

La mia domanda è che se esiste una soluzione (flash/script di azione) che comprime un file e ha un'API javascript?

Lo scenario è questo:

  1. Cercando di caricare 50 MB file XML
  2. Prima di caricare una gru a benna con Javascript e inviarlo al compressore.
  3. Carica il file compresso anziché quello originale.
+0

Ho trovato questo ma non l'ho mai usato (e non Flash qui): http://jszip.stuartk.co.uk/ – AsTheWormTurns

+0

Grazie per il collegamento, ma in pratica avrei bisogno di una soluzione che funzioni in tutti i principali browser come come IE7 +, FF, Safari e Chrome. – feketegy

risposta

5

integrato implementazione di Flash di ByteArray ha un metodo (ByteArray::deflate per sgonfiare il contenuto (del ByteArray) L'algoritmo deflate è il DEFLATE Compressed Data Format Specification version 1.3

Ci; s anche un metodo ByteArray::compress che comprime utilizzando l'zlib algoritmo di

Aspetta un po ', ti scriverò alcuni esempi di codice per utilizzare questa classe ed esporlo a JavaScript.

EDIT

Ho caricato il file alla http://www.filefactory.com/file/cf8a39c/n/demo5.zip

EDIT 2 Per coloro che non hanno potuto scaricare i file:

Il mio codice ActionScript in demo5.fla (compilati a demo5.swf)

import flash.external.ExternalInterface; 
import flash.net.FileReference; 
import flash.events.Event; 
import flash.utils.ByteArray; 

if(ExternalInterface.available) { 
    //flash.system.Security.allowDomain("localhost"); 
    ExternalInterface.addCallback("deflate", doDeflate); 
    ExternalInterface.addCallback("compress", doCompress); 
} 

var method:String="deflate"; 
var b:ByteArray; 
function doCompress(_data:String):void { 
    method="compress"; 
    exec(_data); 
} 

function doDeflate(_data:String):void { 
    method="deflate"; 
    exec(_data); 
} 

function exec(_data:String):void { 
    b=new ByteArray(); 
    b.writeUTFBytes(_data); 
    b.position=0; 
    if(method=="compress") { 
     b.compress(); 
    } else if(method=="deflate") { 
     b.deflate(); 
    } 
    executed(); 
} 

function executed():void { 
    if(ExternalInterface.available) { 
     b.position=0; 
     var str:String=b.readUTFBytes(b.bytesAvailable); 
     ExternalInterface.call("onExec", str); 
    } 
} 

Il mio codice HTML per incorporare il file SWF:

<button onclick="doDeflate()">Deflate</button> 
<button onclick="doCompress()">Compress</button> 
<div id="flashContent"> 
    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="1" height="1" id="demo5" align="middle"> 
     <param name="movie" value="demo5.swf" /> 
     <param name="quality" value="high" /> 
     <param name="bgcolor" value="#ffffff" /> 
     <param name="play" value="true" /> 
     <param name="loop" value="true" /> 
     <param name="wmode" value="window" /> 
     <param name="scale" value="showall" /> 
     <param name="menu" value="true" /> 
     <param name="devicefont" value="false" /> 
     <param name="salign" value="" /> 
     <param name="allowScriptAccess" value="always" /> 

     <embed src="demo5.swf" quality="high" bgcolor="#869ca7" 
      width="1" height="1" name="demo5" align="middle" 
      play="true" loop="false" quality="high" allowScriptAccess="always" 
      type="application/x-shockwave-flash" 
      pluginspage="http://www.macromedia.com/go/getflashplayer"> 
     </embed> 
    </object> 
</div> 

e, infine, il codice javascript:

function doDeflate() { 
    var data="fdg fhnkl,hgltrebdkjlgyu ia43uwriu67ri8m nirugklhvjsd fgvu"; 
    //DATA CONTAINS DATA TO BE DEFLATED 
    thisMovie("demo5").deflate(data); 
} 

function doCompress() { 
    var data="fdg fhnkl,hgltrebdkjlgyu ia43uwriu67ri8m nirugklhvjsd fgvu"; 
    //DATA CONTAINS DATA TO BE DEFLATED 
    thisMovie("demo5").compress(data); 
} 

function onExec(data) { 
    //DATA CONTAINS THE DEFLATED DATA 
    alert(data); 
} 

function thisMovie(movieName) { 
    if (navigator.appName.indexOf("Microsoft") != -1) { 
     return window[movieName]; 
    } else { 
     return document[movieName]; 
    } 
} 
+0

Grazie, lo sto aspettando. :) Inoltre, è facile lavorare con la gestione dei file di Flash? Sto indovinando per ottenere il file necessario per utilizzare la finestra di dialogo del file di Flash, quindi comprimerlo e quindi inviarlo al server in qualche modo ... – feketegy

+0

@feketegy, ho aggiunto il caricamento circa 32 minuti fa (non so perché il commento che ho aggiunto dopo non è stato pubblicato). Ad ogni modo, l'html contiene dei javascript abbastanza auto-esplicativi (con commenti) quindi se non ottieni nulla, non chiedere di chiedere. Un trucco però: dovrai eseguire l'html su un dominio http: // o aggiungere un'eccezione al tuo flash player (a tua scelta) –

+0

Grazie anche a questo, posso passare un file dal tipo di input = "file" />, per il flash? In javascript ho solo accesso al percorso del file e nient'altro. Quindi una volta compresso il file, cosa suggerisci come inviarlo al server? – feketegy

0

C'è qualche libreria javascript di compressione Huffman liberamente disponibile, per esempio https://github.com/wilkerlucio/huffman_js ma penso che il vostro compito è impossibile, perché con JavaScript e HTML non è possibile caricare i dati enorme nel browser o la memoria del client.

+0

Ehi, grazie, ma come ho detto nel commento precedente, ho bisogno di una soluzione che funzioni con IE7 + e altri principali browser. Questa soluzione è in qualche modo un Javascript sperimentale, che non credo possa gestire file XML di grandi dimensioni tra 40 e 50 MB. – feketegy

+0

@feketegy: è solo un suggerimento. Puoi farlo da solo. – Bytemain

+0

controlla questo http://gildas-lormeau.github.io/zip.js/ –

1

Se per qualsiasi motivo non è possibile ottenere una soluzione per funzionare in JavaScript per tutti i principali browser, conosco una libreria di compressione AS3 qui: http://code.google.com/p/ascompress/.

Inoltre, un'opzione meno interessante, se gli utenti di destinazione sono alquanto tecnologici perché non li hanno caricati un file .zip di xml? Quindi sul lato server è possibile decomprimere ed elaborare secondo necessità.

In entrambi i casi sul lato server, è necessario decomprimerlo/decomprimerlo, il che dovrebbe essere facile per trovare soluzioni per Google se non ne hai già uno in mente. .

+0

grazie per il link. Questa soluzione ha un'API JavaScript? Non conosco bene Flash/Actionscript (sono solo un utente). Inoltre, non posso permettermi che gli utenti comprimano in anticipo i file XML. Sfortunatamente questo deve essere un processo automatico, anche se sarebbe l'ideale ... – feketegy

+0

Puoi gestirlo tutto in ActionScript, dato che ha il proprio browser di file. Se ne hai avuto bisogno per parlare con JavaScript per qualsiasi motivo, puoi utilizzare la ExternalInterface di AS3. Pranav ha una bella soluzione sopra. – ToddBFisher

1

Con Silverlight, è possibile zip file sul lato client, e questo approccio funziona in tutti i principali browser. Inoltre, puoi interagire con il tuo widget Silverlight tramite JavaScript. Inoltre, se un utente deve caricare diversi file, il widget Silverlight può mostrare una finestra di dialogo singola per la selezione di tutti i file. L'unico inconveniente è che i tuoi clienti devono installare il plug-in Silverlight.

1

Considerare la revisione di questo altro stackoverflow post. Leggere entrambe le risposte dipinge una buona immagine della realtà della compressione.

Sto considerando l'implementazione di una soluzione Silverlight of Flex che comprime il lato client e se l'utente non desidera installarlo, comprime e decomprime il file server. Aggiornerà questo post quando viene trovata una soluzione.

L'installazione del controllo sarebbe venduta all'utente come un risparmio di tempo, che è normalmente vero. Per il server, sarebbe un risparmio di larghezza di banda e compressione.

4

È possibile utilizzare JSZip. Per l'ingresso, supporta String/ArrayBuffer/Uint8Array/Buffer, ma nonblob s, che è quello che si ottiene da un <input type="file"/> con javascript:

Un oggetto File è tipo specifico di un Blob, e può essere utilizzato in qualsiasi contesto che un blob può

(link)

Quindi si dovrà convertire il file/blob per esempio un ArrayBuffer prima, ad es. utilizzando FileReader.readAsArrayBuffer(). Si noti che questa funzione funziona in modo asincrono, richiedendo un utilizzo di callback. C'è anche un FileReaderSync disponibile, eppure "Questa interfaccia è disponibile solo per i lavoratori poiché abilita l'I/O sincrono che potrebbe potenzialmente bloccare", quindi non vedo nulla di buono nell'usarlo.

(EDIT. Io non sono sicuro, ma credo che si può saltare il blob-> conversione ArrayBuffer ora e semplicemente zip l'oggetto File.)

tutto questo approccio è particolarmente utile se la direttiva di php max_file_uploads era impostato su un piccolo numero per il vostro ospite spazio web, per ora l'unica cosa che si dovrà preoccupare è upload_max_filesize

per riferimento, un estratto di codice seguente (usando JQuery) per mettere diversi file di un ingresso multiple file in una zip prima dell'invio:

// onclick: 
var fileInput = $(':file'); 
var files = []; 
$.each(fileInput[0].files, function(i, file) { 
    files.push(file); 
}); 

var zip = new JSZip(); 
function addFileToZip(n) { 
    if(n >= files.length) { 
     zippingComplete(zip.generate({type:"blob", compression:"deflate"})); 
     return; 
    } 
    var file = files[n];      
    var arrayBuffer; 
    var fileReader = new FileReader(); 
    fileReader.onload = function() { 
     arrayBuffer = this.result; 
     zip.file(file.name, arrayBuffer); 
     addFileToZip(n + 1); 
    }; 
    fileReader.readAsArrayBuffer(file); 
} 
addFileToZip(0); 

function zippingComplete(zip) { 
    formData = new FormData(); 
    formData.append('fileZip', zip); 
    formData.append("param1", "blah"); 
    $.ajax({ 
     data: formData, 
     //... etc 

Dal lato server, si accede a $_FILES["fileZip"].

+0

puoi saltare la conversione blob-> ArrayBuffer nella versione 3+. Ma per la versione precedente (2.6 nel mio caso), la tua soluzione è stata molto utile –

Problemi correlati