【问题标题】:Extracting gzip data in Javascript with Pako - encoding issues使用 Pako 提取 Javascript 中的 gzip 数据 - 编码问题
【发布时间】:2018-05-06 16:58:36
【问题描述】:

我正在尝试运行我期望的一个非常常见的用例:

我需要从 Amazon S3 下载一个 gzip 文件(包含复杂的 JSON 数据集),然后用 Javascript 解压缩(gunzip)它。除了最后的“充气”步骤外,我的一切工作正常。

我正在使用 Amazon Gateway,并且已确认 Gateway 正在正确传输压缩文件(使用 Curl 和 7-zip 来验证生成的数据是否来自 API)。不幸的是,当我尝试使用 Pako 对 Javascript 中的数据进行膨胀时,我遇到了错误。

这是我的代码(注意:response.data 是从 AWS 传输的二进制数据):

apigClient.dataGet(params, {}, {})
      .then( (response) => {
        console.log(response);  //shows response including header and data

        const result = pako.inflate(new Uint8Array(response.data), { to: 'string' });
        // ERROR HERE: 'buffer error'  

      }).catch ( (itemGetError) => {
        console.log(itemGetError);
      });

还尝试了一个版本,通过在 inflate 之前添加以下内容将二进制数据输入拆分为数组:

const charData = response.data.split('').map(function(x){return x.charCodeAt(0); });
const binData = new Uint8Array(charData);
const result = pako.inflate(binData, { to: 'string' });
//ERROR: incorrect header check

我怀疑我的数据编码存在某种问题,并且我没有将其转换为正确的格式,以使 Uint8Array 有意义。

任何人都可以指出正确的方向以使这项工作正常进行吗?

为了清楚起见:

  • 由于列出了上面的代码,我得到一个缓冲区错误。如果我删除 Uint8Array,并尝试处理“result.data”,我会收到错误:“不正确的标头检查”,这让我怀疑这是我的数据的编码/格式问题。李>
  • 原始文件是在 Java 中使用 GZIPOutputStream 压缩的 UTF-8,然后存储为静态文件(即randomname.gz)。

  • 文件通过 AWS 网关以二进制形式传输,因此它是 与原始文件完全相同,所以'curl --output filename.gz {URLtoS3Gateway}' === 从 S3 下载的文件。

  • 当我使用网关将二进制数据编码为“base64”时,我遇到了同样的基本问题,但没有尝试过很多尝试,因为使用“真正的”二进制文件似乎更容易数据而不是在中间添加base64编码/解码。如果这是需要的步骤,我可以重新添加。

我还尝试了在此问题中途发现的一些示例处理:https://github.com/nodeca/pako/issues/15,但这没有帮助(我可能误解了二进制格式 v.array v base64)。

【问题讨论】:

    标签: javascript amazon-s3 gzip pako


    【解决方案1】:

    我能够找出我自己的问题。它与 Javascript 读取的数据格式有关(Javascript 本身或 Angular HttpClient 实现)。我正在阅读“二进制”格式,但它与 pako 识别/使用的格式不同。当我以 base64 格式读取数据,然后使用“atob”转换为二进制时,我能够让它工作。这是我实际实现的(从从 S3 文件存储中获取)。

    1) 构建 AWS API Gateway,它将从 S3 读取先前存储的 *.gz 文件。

    • 为支持二进制的 S3 创建一个标准的“get”API 请求。 (http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-configure-with-console.html)
    • 通过设置“二进制类型”确保网关能够识别输入类型(application/gzip 对我有用,但其他类型的文件,如 application/binary-octet 和 image/png 应该适用于除 *.gz 之外的其他类型的文件) .注意:该设置位于 API 配置屏幕左侧的主要 API 选择列表下。
    • 通过选择 API 方法/{GET} -> 集成请求框并更新“内容处理”项,将“内容处理”设置为“转换为文本(如果需要)”。 (注意:上面链接中的示例建议使用“passthrough”。不要使用它,因为它会传递不可读的二进制格式。)这是实际从二进制转换为 base64 的步骤。

    此时您应该能够通过 URL 下载二进制文件的 base64 版本(在浏览器中或使用 Curl 进行测试)。

    2) 然后我让 API Gateway 生成 SDK 并使用相应的 apiGClient.{get} 调用。

    3) 在调用中,翻译 base64->binary->Uint8 然后解压缩/膨胀它。我的代码:

        apigClient.myDataGet(params, {}, {})
          .then( (response) => {
            // HttpClient result is in response.data
            // convert the incoming base64 -> binary
            const strData = atob(response.data);
    
            // split it into an array rather than a "string"
            const charData = strData.split('').map(function(x){return x.charCodeAt(0); });
    
            // convert to binary
            const binData = new Uint8Array(charData);
    
            // inflate
            const result = pako.inflate(binData, { to: 'string' });
            console.log(result);
          }).catch ( (itemGetError) => {
            console.log(itemGetError);
          });
      }
    

    【讨论】:

    • 这应该在他们的文档中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 2013-07-06
    相关资源
    最近更新 更多