浏览器 Javascript:压缩 Json 到 gzip 并上传到 S3 预签名 URL
Browser Javascript: Compress Json to gzip and upload to S3 presigned URL
如有任何建议,我们将不胜感激。
我的 Web 应用程序中有一个 json 变量,我想通过预先签名的 URL.
gzip 并上传到 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,使用 headers
Content-Type:'application/x-gzip' 和
Content-Encoding: '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
设置 Content-Encoding: gzip
不正确,如果您希望负载在下载后保持 gzip 压缩。这 仅 在您希望 浏览器 透明地解码 gzip 编码时使用——例如在服务 gzipped HTML、JavaScript、CSS、等等
如果使用Content-Encoding: gzip
,则应设置Content-Type
以匹配实际payload,如Content-Type: application/json
.
如果使用 Content-Type: application/x-gzip
,则不应使用 Content-Encoding
,除非您使用不同类型的压缩来重新压缩 gzip 负载(不太可能)。
Content-Type: application/x-gzip
与 Content-Encoding: gzip
结合意味着您将 gzip 文件包装在另一层 gzip 压缩中,并且您希望浏览器删除外层,这不是您在练习。
以下过程对我有用:
使用 Content-Type 生成预签名 URL:'application/json'。提供的文件名应在末尾包含 .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
代码中遵循的步骤:
- 内容类型 header 是 application/json,Content-Encoding 是 gzip。
- 将 JSON
字符串化
- 将字符串转换为 UTF-8
- Gzip 字符串
- 从压缩数据创建文件
- 上传文件到预签名URL
然后您可以从 S3 下载 gzip 文件(它应该会自动被浏览器解压缩)并打开它以验证它是否包含相同的结果。
如有任何建议,我们将不胜感激。 我的 Web 应用程序中有一个 json 变量,我想通过预先签名的 URL.
gzip 并上传到 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,使用 headers Content-Type:'application/x-gzip' 和 Content-Encoding: '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
设置 Content-Encoding: gzip
不正确,如果您希望负载在下载后保持 gzip 压缩。这 仅 在您希望 浏览器 透明地解码 gzip 编码时使用——例如在服务 gzipped HTML、JavaScript、CSS、等等
如果使用Content-Encoding: gzip
,则应设置Content-Type
以匹配实际payload,如Content-Type: application/json
.
如果使用 Content-Type: application/x-gzip
,则不应使用 Content-Encoding
,除非您使用不同类型的压缩来重新压缩 gzip 负载(不太可能)。
Content-Type: application/x-gzip
与 Content-Encoding: gzip
结合意味着您将 gzip 文件包装在另一层 gzip 压缩中,并且您希望浏览器删除外层,这不是您在练习。
以下过程对我有用:
使用 Content-Type 生成预签名 URL:'application/json'。提供的文件名应在末尾包含 .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
代码中遵循的步骤:
- 内容类型 header 是 application/json,Content-Encoding 是 gzip。
- 将 JSON 字符串化
- 将字符串转换为 UTF-8
- Gzip 字符串
- 从压缩数据创建文件
- 上传文件到预签名URL
然后您可以从 S3 下载 gzip 文件(它应该会自动被浏览器解压缩)并打开它以验证它是否包含相同的结果。