【javascript】解析psd文件踩坑

前言

  • 最近一直在做解析psd,踩了很多坑,特此总结下。

psd.js

  • 最开始解析psd自然想到使用node,由于psd.js是node和浏览器都可以用,所以就使用psd.js试了下。
  • 这里就有个坑,3.3.0版本与3.2.2版本由于config配置修改,导致node上只能获取浏览器版本。所以想在node上解析psd的需要使用3.2.1版本。
  • 另外我尝试使用ag-psd这个库解析了下,发现解析出来的格式不太好,并且没有位置信息。
  • psd.js在node上解析依然存在坑。由于这个库在解析图片时并不会释放内存。当你需要每个图层都进行解析时,则会导致内存不够,特别是当文件特别大,图层特别多时。
async readpdf() {
    
    
    const pub = path.resolve(process.cwd(), 'public', 'example.psd');
    const psd = PSD.fromFile(pub);
    psd.parse();
    const tree = await psd.tree().export();
    const descendants = await psd.tree().descendants();
    const pubb = path.resolve(process.cwd(), 'public');
    const tmp = fs.mkdtempSync(path.join(pubb, 'img'));

    return new Promise(res => {
    
    
      const final = v => {
    
    
        // fs.removeSync(tmp)
        res({
    
    
          layer: v,
          document: tree.document,
        });
      };
      const arr = new ArrList(2, final);
      for (let i = 0; i < descendants.length; i++) {
    
    
        const node = descendants[i]; 

        if (node.isGroup()) continue;
        if (node.layer && node.layer.image) {
    
    
          arr.take(async () => {
    
    
            const res = await this.extractImage(node, tmp, i);
            arr.leave(res);
          });
        }
      }
    });
  }

  async extractImage(node, tmp: string, i: number) {
    
    
    return new Promise(async resolve => {
    
    
      try {
    
    
        const name = node.name + i + '.png';
        const tmppath = path.resolve(tmp, name);
        await node.layer.image.saveAsPng(tmppath).catch(function(err) {
    
    
          throw 'psd转换错误' + err;
        });
        const readstream = fs.createReadStream(tmppath);
        const uid = uuid.v4();
        const res = await this.putFileStream(
          readstream,
          'tmpimgs' + node.name + uid + '.png',
          'yehuozhili',
        );
        if (res.success) {
    
    
          resolve({
    
    
            name: node.name,
            width: node.width,
            height: node.height,
            left: node.left,
            right: node.right,
            top: node.top,
            bottom: node.bottom,
            type: 'pic',
            imgSrc: res.hash,
          });
        } else {
    
    
          resolve(node);
        }
      } catch (error) {
    
    
        console.log('psd错误', error);
        resolve(node);
      }
    });
  }
  • 我在node上尝试使用限定进出等待队列进行解析图片,一样解决不了该问题。
  • 这只是一个人传一个大文件内存就爆了,如果很多人传文件,那内存绝对不够,于是就尝试使用浏览器解析。
  • 浏览器解析需要使用createObjectURL转换成url地址进行解析,由于把内存使用放到了客户端,这样服务器压力便小多了,还不用怕文件太大。
  • 尝试了下在node中因内存解析不出的psd文件在浏览器中可以解析:
  			const file = fileList[0];
            const url = window.URL.createObjectURL(file.originFileObj);
            const psd = await PSD.fromURL(url);
            const tree = await psd.tree().export();
            const descendants = await psd.tree().descendants();
            console.log(tree);
            const promiseall = [];
            for (let i = 0; i < descendants.length; i++) {
    
    
              const node = descendants[i];
              if (node.isGroup()) continue;
              if (node.layer && node.layer.image) {
    
    
                promiseall.push(await extractImage(node));
              }
            }
            const result = await Promise.all(promiseall);
            console.log(result);

Guess you like

Origin blog.csdn.net/yehuozhili/article/details/120792137