【问题标题】:Browser Javascript: Compress Json to gzip and upload to S3 presigned URL浏览器 Javascript:将 Json 压缩为 gzip 并上传到 S3 预签名 URL
【发布时间】:2019-12-05 02:44:06
【问题描述】:

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

我能够成功上传 JSON,但我无法 gzip 并上传 JSON。

我尝试构建 gzipped 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 解压缩时,会给出错误消息:'not in gzip format'

我尝试关注的来源:

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

【问题讨论】:

    标签: javascript amazon-s3 gzip pako


    【解决方案1】:

    设置 Content-Encoding: gzip 不正确,如果您希望负载在下载后仍保持 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-gzip 结合Content-Encoding: gzip 意味着您已将 gzip 压缩文件包装在另一层 gzip 压缩中,并且您希望浏览器删除外层,这在实践中是不会做的。

    【讨论】:

      【解决方案2】:

      以下过程对我有用:

      使用 Content-Type: 'application/json' 生成预签名 URL。提供的文件名应在末尾包含 .gz。在返回的预签名 URL 中,扫描 URL 应验证 Content Type 是 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. Content Type 标头为 application/json,Content-Encoding 为 gzip。
      2. 将 JSON 字符串化
      3. 将字符串转换为 UTF-8
      4. 压缩字符串
      5. 从压缩数据创建一个文件
      6. 将文件上传到预签名 URL

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-25
        • 2014-07-26
        相关资源
        最近更新 更多