2013-06-16 10 views
8

Ich brauche einen Klecks auf den Server mit Ajax zu schicken, aber es kann etwas groß am Ende immer, und ich mag Upload-Zeit verringern. Ich habe jszip bereits versucht, aber das gab mir nur eine leere Datei in der Zip. Ich habe auch versucht, btoa(), aber es stellt sich heraus, dass der kodierte Wert am Ende nur [Objekt Blob] anstelle der tatsächlichen Blob-Daten. Welche Möglichkeiten habe ich, Blobs zu komprimieren?Komprimieren einen Klecks in Javascript

war hier der Code, den ich für jszip verwendet:

var zip = new JSZip(); 
zip.file("recording.wav", blobFile); 
var content = zip.generate(); 

ich hängten dann „Inhalt“ zu einem Formdata-Objekt und schickte es an den Server. Auf der Serverseite dekodierte ich die POST-Daten (von base64). Die Zip-Datei wurde problemlos geöffnet, aber recording.wav war eine Datei der Länge 0.

Außerdem habe ich versucht, die LZW-Implementierung unter Verwendung gefunden here. Dies war der zusätzliche Code, den ich verwendet habe, um ihn zu komprimieren:

Dekomprimieren gibt jedoch null zurück.

+1

Wie haben Sie versucht, jszip zu verwenden? Ich glaube nicht, dass ['btoa'] (https://developer.mozilla.org/en-US/docs/Web/API/window.btoa) das ist, was Sie verwenden möchten, wenn ein Problem auftritt, das Base64-Daten erzeugt und das macht die Dinge größer. –

+0

Frage bearbeitet, um zu zeigen, wie jszip verwendet wurde. – Fibericon

+0

Was ist 'blobFile'? –

Antwort

10

Caveat: Komprimieren Dinge wie Audiodateien besser gemacht werden würden unter Verwendung eines Algorithmus speziell für diese Art von Daten gemeint, vielleicht verlustbehaftet etwas. Da ich jedoch weiß, wie schwer es ist, eine sinnvolle verlustfreie Implementierung wie unten beschrieben zu finden, bin ich sehr besorgt, dass es schwierig sein wird, eine gute Java-Implementierung für diese Art von Daten zu finden, die speziell auf Ihre Bedürfnisse zugeschnitten ist.

In jedem Fall hatte ich diese allgemeine Notwendigkeit für die Komprimierung/Dekomprimierung in Javascript, und ich brauchte den gleichen Algorithmus, um sowohl Client (Browser) und Server-Seite (node.js) zu arbeiten, und ich brauchte es um sehr große Dateien zu bearbeiten. Ich hatte jszip ausgecheckt und ich habe auch diesen LZW-Algorithmus unter mindestens fünf oder sechs anderen ausprobiert, von denen keiner den Anforderungen entsprach. Ich kann mich nicht erinnern, was das Problem mit jedem spezifisch war, aber es genüge zu sagen, es ist überraschend schwer, einen guten und schnellen Kompressor/Dekompressor in Javascript zu finden, die sowohl Server- als auch Client-Seite arbeitet und verarbeitet große Dateien! Ich habe mindestens ein Dutzend verschiedene Implementierungen verschiedener Komprimierungsalgorithmen ausprobiert und mich schließlich damit abgefunden - es hat mich noch nicht im Stich gelassen!


UPDATE

Dies ist die ursprüngliche Quelle: https://code.google.com/p/jslzjb/source/browse/trunk/Iuppiter.js?r=2

von jemandem namens Bear - dank Bär, wer auch immer du bist, du bist der Beste. Es ist lzjb: http://en.wikipedia.org/wiki/LZJB


UPDATE 2

  1. ein Problem mit fehlenden Semikolon Korrigierte - sollte das Objekt keine Funktion Fehler nicht mehr geben.
  2. Diese Implementierung auf Daten nicht mehr funktioniert weniger als etwa 80 Zeichen lang sein. Also habe ich das Beispiel aktualisiert, um das zu reflektieren.
  3. die Base64 Encoder/Decoder-Verfahren realisiert auf dem Objekt ausgesetzt sind in der Tat für diese Version übergeben, so ...
  4. Zeit zu sehen, was wir über bestimmte Blob-Typen tun können - was zum Beispiel der beste Ansatz für sein würde, ein Bild gegen Audio usw., wie das für JS Leute im Allgemeinen nützlich wäre ...wird hier mit dem was gefunden wird aktualisiert.

UPDATE 3

Es gibt eine viel bessere Wrapper von Bear als die um die ursprüngliche Iuppiter Quelle ich unten geschrieben. Es ist geschrieben von cscott und auf github hier: https://github.com/cscott/lzjb

Ich werde zu diesem einen, wie es Ströme auch geht.

Unten ist ein Beispiel in Node.js seiner Verwendung mit einer WAV-Datei. Aber bevor das Beispiel kopieren, lassen Sie mich Ihnen die schreckliche Nachricht zuerst, zumindest für diese eine WAV-Datei, die ich versucht:

63128 Jun 19 14:09 beep-1.wav 
63128 Jun 19 17:47 beep-2.wav 
89997 Jun 19 17:47 beep-2.wav.compressed 

So erfolgreich den wav regeneriert (und es gespielt). Der komprimierte scheint jedoch größer als das Original zu sein. Gut schießen. In jedem Fall, könnte es gut sein, Ihre Daten anzuprobieren, Sie wissen nie, Sie könnten Glück haben. Hier ist der Code, den ich verwenden:

var fs = require('fs'); 
var lzjb = require('lzjb'); 

fs.readFile('beep-1.wav', function(err, wav){ 

    // base 64 first 
    var encoded = wav.toString('base64'); 
    // then utf8 - you don't want to go utf-8 directly 
    var data = new Buffer(encoded, 'utf8'); 
    // now compress 
    var compressed = lzjb.compressFile(data, null, 9); 
    // the next two lines are unnecessary, but to see what kind of 
    // size is written to disk to compare with the original binary file 
    var compressedBuffer = new Buffer(compressed, 'binary'); 
    fs.writeFile('beep-2.wav.compressed', compressedBuffer, 'binary', function(err) {}); 
    // decompress 
    var uncompressed = lzjb.decompressFile(compressed); 
    // decode from utf8 back to base64 
    var encoded2 = new Buffer(uncompressed).toString('utf8'); 
    // decode back to binary original from base64 
    var decoded = new Buffer(encoded2, 'base64'); 
    // write it out, make sure it is identical 
    fs.writeFile('beep-2.wav', decoded, function(err) {}); 

}); 

Am Ende des Tages, ich glaube, sein Gehen zu schwierig sein, jede Stufe der Komprimierung auf den meisten Formen von binären Daten zu erreichen, die nicht durch die resultierende Base64-Codierung verprügelt wird . Die Tage der Steuerzeichen für Terminals verfolgen uns noch heute. Sie könnten versuchen, auf eine andere Basis zu wechseln, aber das hat auch Risiken und Probleme.

Siehe das zum Beispiel: What is the most efficient binary to text encoding?

Und: Why don't people use base128?


Eine Sache, auf jeden Fall aber, bevor Sie die Antwort akzeptieren, bitte versuchen Sie es auf Ihrem Blob aus, ich habe Hauptsächlich für die Komprimierung von UTF-8, und ich möchte sicher sein, dass es mit Ihren spezifischen Daten funktioniert.

In jedem Fall ist es hier!

/** 
$Id: Iuppiter.js 3026 2010-06-23 10:03:13Z Bear $ 

Copyright (c) 2010 Nuwa Information Co., Ltd, and individual contributors. 
All rights reserved. 

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are met: 

    1. Redistributions of source code must retain the above copyright notice, 
    this list of conditions and the following disclaimer. 

    2. Redistributions in binary form must reproduce the above copyright 
    notice, this list of conditions and the following disclaimer in the 
    documentation and/or other materials provided with the distribution. 

    3. Neither the name of Nuwa Information nor the names of its contributors 
    may be used to endorse or promote products derived from this software 
    without specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

$Author: Bear $ 
$Date: 2010-06-23 18:03:13 +0800 (星期三, 23 六月 2010) $ 
$Revision: 3026 $ 
*/ 
var fastcompressor = {}; 
(function (k) { 
    k.toByteArray = function (c) { 
     var h = [], 
      b, a; 
     for (b = 0; b < c.length; b++) a = c.charCodeAt(b), 127 >= a ? h.push(a) : (2047 >= a ? h.push(a >> 6 | 192) : (65535 >= a ? h.push(a >> 12 | 224) : (h.push(a >> 18 | 240), h.push(a >> 12 & 63 | 128)), h.push(a >> 6 & 63 | 128)), h.push(a & 63 | 128)); 
     return h 
    }; 
    k.Base64 = { 
     CA: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/", 
     CAS: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_", 
     IA: Array(256), 
     IAS: Array(256), 
     init: function() { 
      var c; 
      for (c = 0; 256 > c; c++) k.Base64.IA[c] = -1, k.Base64.IAS[c] = -1; 
      c = 0; 
      for (iS = k.Base64.CA.length; c < iS; c++) k.Base64.IA[k.Base64.CA.charCodeAt(c)] = c, k.Base64.IAS[k.Base64.CAS.charCodeAt(c)] = c; 
      k.Base64.IA["="] = k.Base64.IAS["="] = 0 
     }, 
     encode: function (c, h) { 
      var b, a, d, e, m, g, f, l, j; 
      b = h ? k.Base64.CAS : k.Base64.CA; 
      d = c.constructor == Array ? c : k.toByteArray(c); 
      e = d.length; 
      m = 3 * (e/3); 
      g = (e - 1)/3 + 1 << 2; 
      a = Array(g); 
      for (l = f = 0; f < m;) j = (d[f++] & 255) << 16 | (d[f++] & 255) << 8 | d[f++] & 255, a[l++] = b.charAt(j >> 18 & 63), a[l++] = b.charAt(j >> 12 & 63), a[l++] = b.charAt(j >> 6 & 63), a[l++] = b.charAt(j & 63); 
      f = e - m; 
      0 < f && (j = (d[m] & 
       255) << 10 | (2 == f ? (d[e - 1] & 255) << 2 : 0), a[g - 4] = b.charAt(j >> 12), a[g - 3] = b.charAt(j >> 6 & 63), a[g - 2] = 2 == f ? b.charAt(j & 63) : "=", a[g - 1] = "="); 
      return a.join("") 
     }, 
     decode: function (c, h) { 
      var b, a, d, e, m, g, f, l, j, p, q, n; 
      b = h ? k.Base64.IAS : k.Base64.IA; 
      c.constructor == Array ? (d = c, m = !0) : (d = k.toByteArray(c), m = !1); 
      e = d.length; 
      g = 0; 
      for (f = e - 1; g < f && 0 > b[d[g]];) g++; 
      for (; 0 < f && 0 > b[d[f]];) f--; 
      l = "=" == d[f] ? "=" == d[f - 1] ? 2 : 1 : 0; 
      a = f - g + 1; 
      j = 76 < e ? ("\r" == d[76] ? a/78 : 0) << 1 : 0; 
      e = (6 * (a - j) >> 3) - l; 
      a = Array(e); 
      q = p = 0; 
      for (eLen = 3 * (e/3); p < eLen;) n = b[d[g++]] << 18 | b[d[g++]] << 
       12 | b[d[g++]] << 6 | b[d[g++]], a[p++] = n >> 16 & 255, a[p++] = n >> 8 & 255, a[p++] = n & 255, 0 < j && 19 == ++q && (g += 2, q = 0); 
      if (p < e) { 
       for (j = n = 0; g <= f - l; j++) n |= b[d[g++]] << 18 - 6 * j; 
       for (b = 16; p < e; b -= 8) a[p++] = n >> b & 255 
      } 
      if (m) return a; 
      for (n = 0; n < a.length; n++) a[n] = String.fromCharCode(a[n]); 
      return a.join("") 
     } 
    }; 
    k.Base64.init(); 
    NBBY = 8; 
    MATCH_BITS = 6; 
    MATCH_MIN = 3; 
    MATCH_MAX = (1 << MATCH_BITS) + (MATCH_MIN - 1); 
    OFFSET_MASK = (1 << 16 - MATCH_BITS) - 1; 
    LEMPEL_SIZE = 256; 
    k.compress = function (c) { 
     var h = [], 
      b, a = 0, 
      d = 0, 
      e, m, g = 1 << NBBY - 1, 
      f, l, j = Array(LEMPEL_SIZE); 
     for (b = 0; b < LEMPEL_SIZE; b++) j[b] = 
      3435973836; 
     c = c.constructor == Array ? c : k.toByteArray(c); 
     for (b = c.length; a < b;) { 
      if ((g <<= 1) == 1 << NBBY) { 
       if (d >= b - 1 - 2 * NBBY) { 
        f = b; 
        for (d = a = 0; f; f--) h[d++] = c[a++]; 
        break 
       } 
       g = 1; 
       m = d; 
       h[d++] = 0 
      } 
      if (a > b - MATCH_MAX) h[d++] = c[a++]; 
      else if (e = (c[a] + 13^c[a + 1] - 13^c[a + 2]) & LEMPEL_SIZE - 1, l = a - j[e] & OFFSET_MASK, j[e] = a, e = a - l, 0 <= e && e != a && c[a] == c[e] && c[a + 1] == c[e + 1] && c[a + 2] == c[e + 2]) { 
       h[m] |= g; 
       for (f = MATCH_MIN; f < MATCH_MAX && c[a + f] == c[e + f]; f++); 
       h[d++] = f - MATCH_MIN << NBBY - MATCH_BITS | l >> NBBY; 
       h[d++] = l; 
       a += f 
      } else h[d++] = c[a++] 
     } 
     return h 
    }; 
    k.decompress = function (c, 
     h) { 
     var b, a = [], 
      d, e = 0, 
      m = 0, 
      g, f, l = 1 << NBBY - 1, 
      j; 
     b = c.constructor == Array ? c : k.toByteArray(c); 
     for (d = b.length; e < d;) { 
      if ((l <<= 1) == 1 << NBBY) l = 1, f = b[e++]; 
      if (f & l) 
       if (j = (b[e] >> NBBY - MATCH_BITS) + MATCH_MIN, g = (b[e] << NBBY | b[e + 1]) & OFFSET_MASK, e += 2, 0 <= (g = m - g)) 
        for (; 0 <= --j;) a[m++] = a[g++]; 
       else break; 
       else a[m++] = b[e++] 
     } 
     if (!("undefined" == typeof h ? 0 : h)) { 
      for (b = 0; b < m; b++) a[b] = String.fromCharCode(a[b]); 
      a = a.join("") 
     } 
     return a 
    } 
})(fastcompressor); 

Und wenn der Speicher dient ... hier ist, wie Sie es verwenden:

var compressed = fastcompressor.compress(""); // data less than this length poses issues. 
var decompressed = fastcompressor.decompress(compressed); 

Rgds .... Hoonto/Matt

Auch, was ich geschrieben habe minimierte ist aber verschönert und sehr leicht angepasst für Benutzerfreundlichkeit. Überprüfen Sie den Link im Update oben für die Original-Sachen.

+0

Ich arbeite jetzt damit. Es sieht vielversprechend aus, aber ich werde es erst wissen, wenn ich fertig bin. – Fibericon

+0

Toll, ich hoffe, es funktioniert, denken Sie daran, LZJB bietet möglicherweise nicht immer die beste Komprimierung, aber es ist sehr schnell (ursprünglich in Sun Microsystems ZFS verwendet). Außerdem gibt es sowohl in der hier veröffentlichten als auch in der Iupiter-Version base64-Kodierungs-/Dekodierungsmethoden. Ich habe sie jedoch nicht auf dem Argument Objekt ausgesetzt. Wie Sie sicherlich wissen, kann die base64-Kodierung einiges an Größe hinzufügen, so dass die Komprimierung nach der Kodierung manchmal nicht viel ist. Was wir wirklich brauchen, sind ein paar gute verlustbehaftete mit der gleichen Geschwindigkeit und Flexibilität wie diese, um eine Compress/Dekomprimierungs-Bibliothek für JS abzurunden. – hoonto

+0

Ich konnte den Code, den Sie eingefügt haben, nicht verwenden (Objekt ist kein Funktionsfehler), aber ich habe den Code von der verlinkten Site verwendet. Das Problem ist, es braucht keinen Blob. Die Verwendung eines Blobs als Argument in Iuppiter.compress() gibt ein leeres Array zurück. Wie hast du einen Blob passiert? – Fibericon

1

JS Zip wird gut funktionieren nur Ihre Syntax korrigieren ..

function create_zip() { 
    var zip = new JSZip(); 
    zip.add("recording.wav", blobfile);//here you have to give blobFile in the form of raw bits >> convert it in json notation.. or stream .. 
    zip.add("hello2.txt", "Hello Second World\n");//this is optional.. 
    content = zip.generate(); 
    location.href="data:application/zip;base64," + content; 
} 

können Sie mehrere Dateien addieren ..

Gerade zip.file wird sich zip.add

und dann zip .generate() erledigt den Rest ..wie Sie getan haben,

oder old Post seinen letzten Teil JavaScript beziehen und NativeBridge hilfreich sein, wenn Sie in diesem Beitrag Benutzerdatensätzen mit Objective C verwenden können, die Sie ignorieren können, aber sendet dieses Objekt mit JavaScript und Socket, Sie können/können verwenden ..

Ich hoffe, dass dies tun wird ... :)

+0

Hallo @MarmiK, können Sie bitte genauer und geben Sie Beispiele mit der Blogdatei, die Sie erwähnen. –

+1

Bitte lassen Sie mich wissen, welchen Abschnitt Sie klären möchten, ich habe in Sortierung beantwortet, um die Frage zu beantworten, JS Zip ist eine Bibliothek (nur zur Klarstellung, ich bin sicher, dass Sie es wissen!), Mit dieser Bibliothek Dinge leicht zu zippen das gehen .. – MarmiK

+0

Danke, @MarkmiK. Ich habe mein Problem bereits gelöst, indem ich in die jsziputils und eine binary: true-Option für die Daten geschaut habe. –