【问题标题】:How to decompress image in JavaScript that was compressed by MS Sql如何解压缩由 MS Sql 压缩的 JavaScript 中的图像
【发布时间】:2021-09-15 07:06:21
【问题描述】:

我有一个包含两列的 SQL 表:

[filedata] [varbinary](max) NULL
[Compressed File Data] [varbinary](max) NULL

[压缩文件数据] 填充有COMPRESS([filedata])。我在[filedata] 中存储了一个图像字节数组。

我有一个反应组件:

import React from 'react';
import Config from 'config';
import { Gunzip, decompress } from 'zlib'
import "./Item.css";

class ItemList extends React.Component {
    constructor() {
        super();
        this.state = {
            name: 'React',
            apiData: [],
        };
    }

    async componentDidMount() {
        console.log('app mounted');
        /*global fetch */
        const tokenString = sessionStorage.getItem("token");
        const token = JSON.parse(tokenString);
        const encodedValue = encodeURIComponent(token.customerNumber);
        const response = await fetch(Config.apiUrl + `/api/Items?customerNumber=${encodedValue}`, {
            method: "GET",
            headers: {
                'Content-Type': "application/json",
                'Authorization': 'Bearer ' + token.token
            }
        });
        
        const json = await response.json();
        console.log(json);
        this.setState({ itemList: json.$values });        
    }

    //DecompressImage(compressedImage) {
    //    const buffer = Buffer.from(`${compressedImage}`, 'base64');
    //    Gunzip(buffer, (err, buffer) => {
    //        if (err) {
    //            console.error('An error occurred:', err);                
    //        }
    //        console.log(buffer.toString());
    //        return buffer;
    //    });
    //}

    DecompressImage(compressedImage) {
        console.log(compressedImage);
        var response = new Uint8Array(compressedImage);
        var compressed = response.subarray(0, response.byteLength - 4);
        var gunzip = new Gunzip(compressed);
        var decompress = gunzip.decompress();
        console.log(decompress)
        return decompress;
    }


    render() {
        const items = this.state.itemList;

        return (
            <table className="table table-striped table-bordered">
                <thead>
                    <tr>
                        <th>Item Number</th>
                        <th>Item Description</th>
                        <th>Item Image</th>
                    </tr>
                </thead>
                <tbody>
                    {items && items.map((item, index) =>
                        <tr key={index}>
                            <td>{item.itemNumber}</td>
                            <td>{item.itemDescription}</td>
                            <td><img className="fit-picture" src={"data:image/png;base64," + this.DecompressImage(item.imageData)} id={item.itemNumber + "Img"} alt={item.itemNumber} /></td>
                        </tr>
                    )}
                </tbody>
            </table>
        );
    }
}
export default ItemList;

对于我的生活,我无法让DecompressImage(compressedImage) 工作。这在我尝试使用压缩数据之前有效。注释的DecompressImage(compressedImage) 什么也不返回,也没有日志条目。第二个解压有错误,解压未定义。

我尝试过以下代码:nodejs 或这个stackoverflow 问题。

任何帮助将不胜感激。

nodejs 版本 14.17.1

【问题讨论】:

  • 为什么你需要在事后这样做,而不是在你的服务器端查询中使用 DECOMPRESS 到 mssql?您将获得正常的图像数据,然后您可以使用透明 gzip 压缩将其发送到客户端(即,您的服务器应该已经使用 gzip 或 brotli 将所有数据发送到客户端,并且浏览器的网络部分将解压缩该数据所以你和你的代码都不需要担心手动解压缩任何东西)?
  • @Mike'Pomax'Kamermans API 查询 sql server 并检索压缩图像,然后将其转发给仍压缩的 react 应用程序。那是两次穿越电线。我可以在 API 上解压,但为什么?
  • 第一次旅行不是在重要的线路上,但它是在针对连接进行优化的主机上的两台服务器之间,这两个服务器几乎都在光纤上,并且能够在不眨眼的情况下处理更多数量级的数据比你能用的。除非您实际上由于您推送的数据量而遇到成本问题,否则从数据库中以解压缩格式获取图像并不是您应该担心的事情意味着您没有进一步的编解码器不兼容问题?
  • 注意:获得权威答案可能仍然是一个有趣的问题,但作为一个关于现实世界实现的问题,这似乎是您不需要的过早优化的主要示例在您扩展到数以百万计的交易之前,您无需担心。
  • (当然,请注意,您似乎只是使用了错误的解码器,various pages 解释二进制压缩/解压缩字段use glib, not zlib,所以赏金可能有点小过早的=)

标签: javascript zlib reactjs.net


【解决方案1】:

首先,确保您将 Base64 字符串作为DecompressImage() 的输入。问题可能是当您需要 ArrayBuffer 或 Base64 字符串时,您得到的是十六进制字符串。网络上的十六进制字符串比未压缩的数据效率更低。如果您确定您实际上使用的是 JSON 中的 Base64 字符串,则将其转换为 Uint8Array 并解压缩。

既然您已确保您有一个 base64 输入,请注意 NPM zlib 库已过时,与 pakofflate(我自己的库)等现代替代品相比,其性能非常低。由于fflatepako 更小更快,我将使用它来回答这个问题。以下是解压缩数据的方法:

// Install both fflate and base64-js for maximum speed
import * as b64 from 'base64-js';
import { gunzipSync } from 'fflate';
// This should replace DecompressImage
// Decompresses gzip + base64 to base64
function decompressToBase64(base64String) {
  const bytes = b64.toByteArray(base64String);
  const decompressed = gunzipSync(bytes);
  return b64.fromByteArray(decompressed);
}

【讨论】:

  • 我在模块 base64-js 中遇到错误。 TypeError: b64 is undefined./ClientApp/node_modules/base64-js/index.js:23。版本 base64-js@1.5.1.
  • 确保导入正确,可能是import b64 from 'base64-jsconst b64 = require('b64-js');
  • 与新导入行import b64 from 'base64-js'相同的错误
  • 我的一个项目的 imageData 为空值。添加了空检查,一切正常。
猜你喜欢
  • 2013-08-07
  • 1970-01-01
  • 1970-01-01
  • 2019-08-06
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多