【问题标题】:How can I process more than 500 MB worth of images?如何处理超过 500 MB 的图像?
【发布时间】:2022-08-18 02:20:14
【问题描述】:

代码在处理小于 500 MB 的图像时可以正常工作。 (我正在尝试做 +25 GB 的价值)有没有办法修改代码以使其适用于大量图像?

我收到如下所示的错误:

节点:内部/进程/承诺:279 triggerUncaughtException(err, true /* fromPromise */); ^

[错误:EIO:i/o 错误,写入] { 错误号:-5, 代码:\'EIO\', 系统调用:\'写\' }

或这个:

节点:内部/进程/承诺:279 triggerUncaughtException(err, true /* fromPromise */); ^

错误:读取 ENOTCONN 在 tryReadStart (节点:net:614:20) 在 Socket._read (node:net:625:5) 在 Socket.Readable.read(节点:内部/流/可读:487:10) 在 Socket.read (node:net:666:39) 在新的 Socket (node:net:415:12) 在 Object.Socket (node:net:286:41) 在 createSocket(节点:内部/子进程:328:14) 在 ChildProcess.spawn(节点:内部/child_process:445:23) 在 Object.spawn (节点:child_process:700:9) 在 execa (file:///mnt/d/Projects/GH_2022/imagemin-mozjpeg/node_modules/execa/index.js:84:26) { 错误号:-107, 代码:\'ENOTCONN\', 系统调用:\'读\', originalMessage: \'读取 ENOTCONN\', 短消息:\'命令因 ENOTCONN 失败:/mnt/d/Projects/GH_2022/imagemin-mozjpeg/node_modules/mozjpeg/vendor/cjpeg -quality 75\\n\' + \'读取 ENOTCONN\', 命令:\'/mnt/d/Projects/GH_2022/imagemin-mozjpeg/node_modules/mozjpeg/vendor/cjpeg -quality 75\', 转义命令:\'\"/mnt/d/Projects/GH_2022/imagemin-mozjpeg/node_modules/mozjpeg/vendor/cjpeg\" -quality 75\', 退出代码:未定义, 信号:未定义, 信号描述:未定义, 标准输出:缓冲区(0)[Uint8Array] [], 标准错误:缓冲区(0)[Uint8Array] [], 失败:真的, 超时:假, 已取消:假, 被杀:假 }

这是我目前拥有的:

import imagemin from \'imagemin\';
import imageminMozjpeg from \'imagemin-mozjpeg\';

import { promises as fsPromises } from \'node:fs\';
import { promisify } from \'node:util\';
import path from \'node:path\';
import fs from \'graceful-fs\';

const writeFile = promisify(fs.writeFile);

const srcdir = \'images/source\';
const distdir = \'images/dist\';

imagemin([srcdir + \'/**/*.{jpg,jpeg,png}\'], {
    plugins: [
        imageminMozjpeg({
            quality: 75
        })
    ]
}).then(files => files
    .forEach(async v => {
        let source = path.parse(v.sourcePath);
        v.destinationPath = `${source.dir.replace(srcdir, distdir)}/${source.name}${source.ext}`;
        await fsPromises.mkdir(path.dirname(v.destinationPath), { recursive: true });
        await writeFile(v.destinationPath, v.data);
    })
);
  • 您可以先将forEach() 替换为常规的for 循环。 .forEach() 不知道承诺,因此您的代码试图一次运行所有操作,而不是一个接一个地运行。
  • [Error: EIO: i/o error, write]。你确定你的硬件没问题?
  • @jfriend00 你能给我举个例子吗?我不习惯 nodejs 样式的 javascript 以及所有的 async、await、promise 等。另外,你在哪里可以了解哪些方法是 promise 感知的?
  • 您可以像previous answer by myself 中描述的那样进行批处理或滑动窗口方法,这应该通过仍然控制正在使用的内存量来为您提供相当高的吞吐量。答案与图像处理无关,但原理保持不变。您将处理图像,而不是使用fetch() 发出请求。
  • @robertklep:我当然希望如此!

标签: javascript node.js image-compression imagemin mozjpeg


【解决方案1】:

对于初学者来说,.forEach() 不支持承诺(它根本不注意回调的返回值)。因此,您正在尝试一次并行运行所有文件操作。我的猜测是您的文件句柄用完了(基于错误)。您可以按顺序运行它们(这应该会减少内存和文件句柄要求),如下所示:

imagemin([srcdir + '/**/*.{jpg,jpeg,png}'], {
    plugins: [
        imageminMozjpeg({
            quality: 75
        })
    ]
}).then(async files => {
    for (let v of files) {
        let source = path.parse(v.sourcePath);
        v.destinationPath = `${source.dir.replace(srcdir, distdir)}/${source.name}${source.ext}`;
        await fsPromises.mkdir(path.dirname(v.destinationPath), { recursive: true });
        await writeFile(v.destinationPath, v.data);
    }
}).catch(err => {
    console.log(err);
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-19
    • 2020-09-28
    • 2017-10-08
    • 2020-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-05-14
    • 1970-01-01
    相关资源
    最近更新 更多