nodejs中解决压缩包乱码

不知小伙伴们在node开发中有没有解压zip的场景。我这边在处理zip乱码时,查阅了许多资料,最后也使用jszip成功解决了此问题,在此把处理方法分享给大家,有这个需求的可以测试下,希望能帮到大家。
import * as JSZip from 'jszip';
import * as iconv from 'iconv-lite';

const detect = require('charset-detector');


export async function getZipEncodingCharsets(data: Buffer | Blob): Promise<any> {
  let allBytes: any[] = [];
  await JSZip.loadAsync(data, {
    // @ts-ignore
    decodeFileName(bytes: any) {
      allBytes = allBytes.concat(bytes);
      return bytes.toString();
    },
  });
  return detect(allBytes);
}

/**
 * 返回识别出的所有编码
 * @param data
 */
export async function getZipEncodingCharsetNames(data: Buffer | Blob): Promise<string[]> {
  let charsets = await getZipEncodingCharsets(data);
  if (charsets.length === 0) {
    return [];
  }
  const ignoreCharsetArr: string[] = [
    'UTF-32BE',
    'UTF-32LE',
  ];
  charsets = charsets.filter((c: any) => !ignoreCharsetArr.includes(c.charsetName));
  const zhCharset = charsets.find((c: any) => c.lang === 'zh');
  let charsetNames: string[] = [];
  if (zhCharset) {
    charsetNames.push(zhCharset.charsetName);
  }
  charsetNames.push('UTF-8');
  charsetNames.push('GB18030');
  charsetNames = charsetNames.concat(charsets.map((c: any) => c.charsetName));
  charsetNames = charsetNames.filter((
    item: string,
    index: number,
    array: string[],
  ) => array.indexOf(item) === index);
  return charsetNames;
}

function checknum(value: string): boolean {
  const Regx = /^[A-Za-z0-9]*$/;
  return Regx.test(value);
}

function isMessyCode(strName: string) {
  const temp = strName.replace(/\p{L}|\p{N}|_|-|\.|\/|\s|\(|\)/g, '');
  const ch = temp.split('');
  const chLen = ch ? ch.length : 0;
  for (let i = 0; i < chLen; i += 1) {
    const c = ch[i];
    if (!checknum(c)) {
      const str = ch[i];
      const patt1 = new RegExp(/[\u4e00-\u9fa5]+/);
      if (!patt1.test(str)) {
        return true;
      }
    }
  }
  return false;
}

async function getTheRightZip(data: Buffer | Blob, charsets: string[]): Promise<{ zip: JSZip, charset: string } | void> {
  if (!charsets || charsets.length === 0) {
    return;
  }
  const charset = charsets.shift();
  if (!charset) {
    return;
  }
  // @ts-ignore
  const zip = await JSZip.loadAsync(data, {
    // @ts-ignore
    decodeFileName(bytes: any) {
      try {
        return iconv.decode(bytes, charset);
      } catch (e) {
        console.error(e);
      }
    },
  });
  let str = '';
  zip.forEach((rp: string) => {
    str += rp;
  });
  const isHasMessyCode = isMessyCode(str);
  if (!isHasMessyCode) {
    // @ts-ignore
    return {
      zip,
      charset,
    };
  }
  return await getTheRightZip(data, charsets);
}

/**
 * 返回解码过后的zip
 * 注意:当解码失败时不会返回zip
 * @param data
 */
export async function getZipWithAutoDetectedCharset(data: Buffer | Blob): Promise<{ zip: JSZip, charset: string }> {
  const charsets = await getZipEncodingCharsetNames(data);
  const result = await getTheRightZip(data, charsets).catch(e => console.error(e));
  let zip;
  let charset: string = '';
  if (result) {
    zip = result.zip;
    charset = result.charset;
  }
  if (!zip) {
    charset = 'utf-8';
    // @ts-ignore
    zip = await JSZip.loadAsync(data, {
      // @ts-ignore
      decodeFileName(bytes: any) {
        try {
          return Buffer.from(bytes, 'utf-8');
        } catch (e) {
          console.error(e);
        }
      },
    });
  }
  // @ts-ignore
  return {
    zip,
    charset,
  };
}

node-stream-zip 是查看和提取大型 ZIP 文件的 Node.js 库。特性:从不加载完整的归档到内存,一切都是通过块读取大型归档支持所有操作都是非阻塞,非同步 i/o快速初始化无依赖,无二进制组件内置 zlib 模块解压deflate, deflate64, sfx, macosx/windows 内置归档ZIP64 支持安装$ npm install node-stream-zip使用var StreamZip = require('node-stream-zip');   var zip = new StreamZip({       file: 'archive.zip',       storeEntries: true     }); zip.on('error', function(err) { /*handle*/ }); zip.on('ready', function() {     console.log('Entries read: '   zip.entriesCount);     // stream to stdout     zip.stream('node/benchmark/net/tcp-raw-c2s.js', function(err, stm) {         stm.pipe(process.stdout);     });     // extract file     zip.extract('node/benchmark/net/tcp-raw-c2s.js', './temp/', function(err) {         console.log('Entry extracted');     });     // extract folder     zip.extract('node/benchmark/', './temp/', function(err, count) {         console.log('Extracted '   count   ' entries');     });     // extract all     zip.extract(null, './temp/', function(err, count) {         console.log('Extracted '   count   ' entries');     });     // read file as buffer in sync way     var data = zip.entryDataSync('README.md'); }); zip.on('extract', function(entry, file) {     console.log('Extracted '   entry.name   ' to '   file); }); zip.on('entry', function(entry) {     // called on load, when entry description has been read     // you can already stream this entry, without waiting until all entry descriptions are read (suitable for very large archives)      console.log('Read entry ', entry.name); });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值