2013-06-16 6 views
8

Мне нужно отправить blob на сервер с помощью ajax, но он может стать несколько большим, и я хотел бы уменьшить время загрузки. Я уже пробовал jszip, но это просто дало мне пустой файл внутри zip. Я также попробовал btoa(), но оказалось, что закодированное значение заканчивается тем, что [объект Blob] вместо фактических данных blob. Каковы мои варианты сжатия капли?Сжатие blob в javascript

Здесь был код, который я использовал для jszip:

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

Затем я приложил «содержание» к объекту FormData и отправил его на сервер. На стороне сервера я расшифровал данные POST (от base64). Файл zip был открыт только отлично, но record.wav был файлом длиной 0.

Кроме того, я попытался использовать реализованную реализацию LZW here. Это был дополнительный код, который я использовал для его сжатия:

var compressed; 
var reader = new FileReader(); 
reader.onload = function(event){ 
    compressed = LZW.compress(event.target.result); 
}; 
reader.readAsText(blobFile); 

Однако при распаковке он возвращает null.

+1

Как вы пытались использовать jszip? Я не думаю, что ['btoa'] (https://developer.mozilla.org/en-US/docs/Web/API/window.btoa) - это то, что вы хотите использовать, если размер проблемы, который создает данные Base64 и это делает вещи больше. –

+0

Вопрос отредактирован, чтобы показать, как использовался jszip. – Fibericon

+0

Что такое 'blobFile'? –

ответ

10

Предостережение: сжатие таких вещей, как аудиофайлы, было бы лучше сделано с использованием алгоритма, специально предназначенного для данных такого типа, возможно, что-то потерянного. Тем не менее, зная, как трудно найти разумную реализацию без потерь, как показано ниже, я очень обеспокоен тем, что будет трудно найти хорошую реализацию в Javascript для такого типа данных, специально отвечающего вашим потребностям.

В любом случае у меня была эта общая необходимость в сжатии/распаковке в Javascript, и мне нужен был тот же алгоритм для работы как с клиентом (браузером), так и с сервером (node.js), и мне это было нужно для работы с очень большими файлами. Я проверил jszip, и я также попробовал этот алгоритм LZW среди не менее пяти или шести других, которые не удовлетворяли требованиям. Я не могу вспомнить, в чем проблема с каждым из них конкретно, но достаточно сказать, что на удивление трудно найти хороший и быстрый компрессор/декомпрессор FAST в javascript, который работает как на стороне сервера, так и на стороне клиента и обрабатывает большие файлы! Я пробовал по крайней мере дюжину различных реализаций различных алгоритмов сжатия, и, наконец, решил с этим - он еще не подвел меня!


UPDATE

Это оригинальный источник: https://code.google.com/p/jslzjb/source/browse/trunk/Iuppiter.js?r=2

По некоему Медведь - спасибо Медведь, кто ты, что ты лучший. Это LZJB: http://en.wikipedia.org/wiki/LZJB


UPDATE 2

  1. Исправлена ​​проблема с отсутствующими точкой с запятой - не должны дать не возражали ошибку функции больше.
  2. Эта реализация перестает работать с данными длиной менее 80 символов. Поэтому я обновил этот пример, чтобы отразить это.
  3. Реализованы методы кодирования/декодирования base64 на самом деле выставлены на объект, переданный для этой версии, поэтому ...
  4. В настоящее время мы видим, что мы можем делать с конкретными типами блоков - что, например, лучший подход был бы для образ против аудио и т. д., поскольку это было бы полезно для людей JS вообще ...обновит здесь, что будет найдено.

UPDATE 3

Существует гораздо лучше обертка вокруг оригинального источника Iuppiter от Медведя, чем тот, который я разместил ниже. Здесь написано cscott и github: https://github.com/cscott/lzjb

Я буду переключаться на этот, так же как и потоки.

Ниже приведен пример использования Node.js в wav-файле. Но перед копированием примера, позвольте мне дать вам страшную новость первый, по крайней мере, для этого один WAV файла, который я попробовал:

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 

Так он успешно возродил WAV (и он играл). Однако сжатый, по-видимому, больше оригинала. Хорошо стреляй. В любом случае, может быть полезно попробовать свои данные, вы никогда не знаете, вам может повезти. Вот код, который я использовал:

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) {}); 

}); 

В конце концов, я думаю, что его будет слишком трудно достичь любого уровня сжатия на большинстве форм двоичных данных, которые не затерты в результате кодирования base64 , Дни контрольных символов для терминалов все еще преследуют нас по сей день. Вы можете попробовать перейти на другую базу, но у нее есть свои риски и проблемы.

Смотреть это, например: What is the most efficient binary to text encoding?

И это: Why don't people use base128?


Одна вещь, хотя, безусловно, прежде чем принять ответ, пожалуйста, пожалуйста, попробуйте его на своем сгустка, Я в основном использовал его для сжатия utf-8, и я хотел бы быть уверенным, что он работает с вашими конкретными данными.

В любом случае, вот оно!

/** 
$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); 

И если память ... вот как вы его используете:

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

Rgds .... Hoonto/Matt

Кроме того, что я отправил это уменьшенная, но украсил , и очень немного приспособлены для простоты использования. Проверьте ссылку в обновленном обновлении для оригинального материала.

+0

Я работаю с этим сейчас. Это выглядит многообещающе, но я не буду знать, пока не закончу. – Fibericon

+0

Отлично, я надеюсь, что это сработает, имейте в виду, что LZJB может не всегда обеспечивать наилучшее сжатие, но он очень быстрый (первоначально использовался в Sun Microsystems ZFS). Кроме того, существуют методы кодирования/декодирования base64 как в версии, опубликованной здесь, так и в Iupiter. Однако я не раскрывал их на объекте аргумента. Кроме того, как я уверен, вы знаете, кодировка base64 может добавить немного размера, поэтому сжатие пост-кодирования может быть не так уж и много. Нам действительно нужны несколько хороших проигрышей с такой же скоростью и гибкостью, как и этот, чтобы завершить библиотеку сжатия/распаковки для JS. – hoonto

+0

Мне не удалось использовать код, который вы вставили (объект не является функцией ошибки), но я использовал код с сайта, который вы связали. Проблема в том, что он не принимает blob. Использование blob в качестве аргумента в Iuppiter.compress() возвращает пустой массив. Как вы прошли мимо блоба? – Fibericon

1

JS Zip будет работать нормально только исправить синтаксис ..

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; 
} 

вы можете добавить несколько файлов тоже ..

Просто zip.file станет zip.add

и затем пронестись .generate() сделает все остальное ..как вы это делали,

или обратитесь к old Post в свою последнюю часть JavaScript, а NativeBridge будет полезен, если вы сможете использовать в этих публикациях пользователя, используя Objective C, которые вы можете игнорировать, но отправляет этот объект с использованием JavaScript и Socket, который вы можете/можете использовать ..

Я надеюсь, что это будет сделано ... :)

+0

Привет @MarmiK, не могли бы вы быть более конкретными и дать какие-либо примеры в блоге, который вы упоминаете. –

+1

Пожалуйста, дайте мне знать, в какую секцию вы хотите уточнить, я ответил, чтобы ответить на вопрос, JS zip - это библиотека (просто для разъяснения, я уверен, что вы это знаете!), Используя эту библиотеку, становится легко застегиваться на the go .. – MarmiK

+0

спасибо, @MarkmiK. Уже решена моя проблема, просмотрев jsziputils и двоичный: истинный вариант для данных. –

Смежные вопросы