浏览器Javascript:将Json压缩为gzip,然后上传到S3预签名URL

时间:2019-07-26 18:30:00

标签: javascript amazon-s3 gzip pako

任何建议将不胜感激。 我的网络应用程序中有一个json变量,我想对其进行gzip压缩并通过预先签名的URL上传到S3。

我能够成功上传JSON,但是我无法对JSON进行gzip后再上传。

我尝试构建gzip json的三种不同方法是:

// example json
const someJson = { testOne: 'a', testTwo: 'b' };

// Attempt one
const stringUtf16 = JSON.stringify(someJson);
const resultAsBinString = pako.gzip(stringUtf16);

// Attempt two
const stringUtf16 = JSON.stringify(someJson);
const resultAsBinString = pako.gzip(stringUtf16, { to: 'string' });

// Attempt three
const stringUtf16ThatWeNeedInUtf8 = JSON.stringify(someJson);
const stringUtf8 = unescape(encodeURIComponent(stringUtf16ThatWeNeedInUtf8));
const resultAsBinString = pako.gzip(stringUtf8);

对于每次尝试,我都通过Angular的HTTP客户端通过标头上传resultAsBinString 内容类型:“ application / x-gzip”和 内容编码:“ gzip”

但是,当文件(然后,如果经常出现网络错误)随后从S3下载时,当尝试在终端中使用gzip或gunzip解压缩时,会出现错误消息:“非gzip格式”

我尝试遵循的来源:

https://github.com/nodeca/pako/issues/55 https://github.com/nodeca/pako/blob/master/examples/browser.html

2 个答案:

答案 0 :(得分:0)

如果您期望有效负载在下载后仍保持压缩状态,则设置Content-Encoding: gzip不正确。 仅在您希望浏览器透明地解码gzip编码时使用-例如在提供gzip压缩的HTML,JavaScript,CSS等时

如果使用Content-Encoding: gzip,则应将Content-Type设置为与实际有效负载相匹配,例如Content-Type: application/json

如果使用Content-Type: application/x-gzip,则不应该使用Content-Encoding,除非您使用另一种压缩方式重新压缩gzip有效负载(不太可能)。

Content-Type: application/x-gzipContent-Encoding: gzip结合使用意味着您已将gzip压缩文件包装在gzip压缩的另一层中,并且希望浏览器删除外层,这实际上是您从未做过的。

答案 1 :(得分:0)

以下过程对我有用:

生成Content-Type:'application / json'的预签名URL。提供的文件名应在末尾包含.gz。在返回的预签名URL中,浏览URL应该验证内容类型为application / json。

因为我确定我的JSON不包含会中断到UTF-8转换的字符串,所以我执行以下操作(Angular中的代码,但它传达了结构):

const headers = new HttpHeaders({
    'Content-Type': 'application/json',
    'Content-Encoding': 'gzip'
});  //1
const httpOptions = {
    headers: headers
};
const str = JSON.stringify(geoJson); //2
const utf8Data = unescape(encodeURIComponent(str)); //3
const geoJsonGz = pako.gzip(utf8Data); //4
const gzippedBlob = new Blob([geoJsonGz]); //5
upload = this.httpClient.put(presignedUploadUrl, gzippedBlob, httpOptions); //6

代码中遵循的步骤:

  1. “内容类型”标头是application / json,而“内容编码”是gzip。
  2. 将JSON字符串化
  3. 将字符串转换为UTF-8
  4. 将字符串Gzip压缩
  5. 从压缩数据创建文件
  6. 将文件上传到预先签名的URL

然后您可以从S3下载压缩后的文件(浏览器应自动将其解压缩)并打开它以验证其是否包含相同的结果。