huaweicloud / huaweicloud-sdk-nodejs-obs

Apache License 2.0
27 stars 10 forks source link

getObject返回的格式与官方文档格式不一致 #26

Open jiulanrensan opened 10 months ago

jiulanrensan commented 10 months ago

官方文档返回结果的Content如下: 微信截图_20240129143321

但实际上sdk返回的为string类型,查sdk代码,发现在响应处对buffer对象做了body.toString('utf8')处理


问题:

  1. 是否会对代码进行修改,返回buffer数据类型?
  2. 下载zip时,如果强制转string类型,会无法再转buffer类型,见此链接
liqiuqiu111 commented 4 months ago

sdk本身不会转译buffer类型

acecode commented 1 month ago

最近在开发处理 .npy 文件 发现使用 obs SDK 取回的文件内容无法解析

示例 .npy 文件

复现步骤

  1. 上传 .npy 文件到 obs

  2. 使用 SDK 取回

    async function loadNpy() {
    const result = await sourceObs.getObject({
        Bucket: 'demo',
        Key: '001.npy',
        ResponseHook(res) {
            res.on('data', (chunk) => {
                console.log('res.data[0]', chunk.readUint8(0));
                console.log('res.data[1]', chunk.readUint8(1));
                console.log('res.data[2]', chunk.readUint8(2));
            })
        }
    })
    const content = result.InterfaceResult.Content;
    const buffer = Buffer.from(content, 'binary');
    
    console.log('content[0]', buffer.readUInt8(0));
    console.log('content[1]', buffer.readUInt8(1));
    console.log('content[2]', buffer.readUInt8(2));
    
    }

    输出

    res.data[0] 147  <--
    res.data[1] 78
    res.data[2] 85
    content[0] 253  <--
    content[1] 78
    content[2] 85
  3. 第一个 byte 从 147 变为 253 了

toString 的 位置

opt.InterfaceResult[key] = body.toString('utf8')

// utils.js

Utils.prototype.getRequest

serverback.on('end',
   ...
    if(body.length > 0 && ('data' in model)){
   ...
       if(model.data.type === 'body'){
       ....
       opt.InterfaceResult[key] = body.toString('utf8');

核心步骤复现

// 截取自 .npy 文件
// Python numpy 导出数值文件

const data = [147,78,85,77,80,89]
const buffer = Buffer.from(data)
const utf8String = buffer.toString('utf8')
const buffer1 = Buffer.from(utf8String, 'binary')

let bytes = []
let bytes1 = []

for(let i = 0; i < buffer.byteLength; i++) {
    bytes.push(buffer.readUInt8(i))
    bytes1.push(buffer1.readUInt8(i))
}

console.log(bytes)
console.log(bytes1)

// [ 147, 78, 85, 77, 80, 89 ]
// [ 253, 78, 85, 77, 80, 89 ]

临时解决方案 从 saveAsStream 方式中转

ObsClient.prototype.getObjectBuffer = function(param, callback) {

    function isFunction(a) {
        return typeof a === 'function';
    }
    const addParam = {
        // 默认会先转字符串 utf8
        // 导致读取首字节错误
        // 147 -> 253
        // @see https://github.com/huaweicloud/huaweicloud-sdk-nodejs-obs/blob/5cc75e293fd7481d581e5edfefb58825c7b5ced3/lib/utils.js#L1604
        // 这里手工 从 stream 读取
        SaveAsStream : true,
    };
    const _param = param && !isFunction(param)
        ? {
            ...param,
            ...addParam,
        }
        : addParam;
    const _cb = isFunction(param)
        ? param
        : isFunction(callback)
            ? callback
            : undefined;

    const p = this.getObject(_param)
        .then(result => {
            if (result.CommonMsg.Status < 300) {
                return new Promise((resolve, reject) => {
                    const stream = result.InterfaceResult.Content;
                    let buffers = []
                    stream.on('data', (chunk) => {
                        buffers.push(chunk);
                    })
                    stream.on('end', () => {
                        resolve(Buffer.concat(buffers))
                    })
                    stream.on('error', reject)
                })
            } else {
                throw result;
            }
        })
        .then(buffer => {
            if (_cb) {
                _cb(null, buffer);
            } else {
                return buffer;
            }
        })
        .catch(err => {
            if (_cb) {
                _cb(err)
            } else {
                throw err;
            }
        })
    return _cb ? undefined : p;
}