首页 > 解决方案 > 使用 Node JS(fs 和 http)保存后无法打开 JPG 或 PNG

问题描述

我的代码的目标是 1)用户将发送图像 URL 2)机器人读取 URL 3)机器人将图像保存到“图像”文件夹 4)机器人使用 tfjs 将图像转换为张量 5)机器人使用 COCO-SSD JS 作为预训练模型(以图像张量作为参数)并打印然后发送结果。

现在,我的问题是,每当我尝试使用它们的 URL 保存图像时,我都会返回一个程序或 Windows 都无法读取的文件!

它工作了一次,能够打开和使用文件。但现在返回 Windows 10 无法读取 .PNG 或 .JPG 文件的文件。

这是我的代码:

    const {Client, MessageAttachment} = require('discord.js');
    const bot = new Client();
    const tf = require('@tensorflow/tfjs-node');
    const ts = require('@tensorflow/tfjs-core');
    require('@tensorflow/tfjs-backend-cpu');
    require('@tensorflow/tfjs-backend-webgl');
    const coco = require('@tensorflow-models/coco-ssd');
    const fs = require('fs');
    const fetch = require("node-fetch");
    const https = require('https');
    const request = require('request');
  
    bot.on('message', gotMessage);

    function gotMessage(msg) {
        if(msg.content === '!object')  {   
            const attachments = (msg.attachments).array();

            const filepath = "./images/" + Date.now() + "J" + ".jpg";
            console.log(filepath);
            const imageurl = attachments[0].url;

            saveImageToDisk(imageurl,filepath)

            const img_buffer = fs.readFileSync(filepath)
            const img = tf.node.decodeImage(img_buffer)

            coco.load().then(model => {
                // detect objects in the image.
                model.detect(img).then(predictions => {
                    console.log('Predictions: ', predictions);
                });
              });
            msg.reply('Enjoy');
            msg.channel.send(attachments[0].url);
        }
    }
    function saveImageToDisk(url,path) {
        var fullUrl = url;
        var localPath = fs.createWriteStream(path);
        var request = https.get(fullUrl,function(response) { 
            console.log(response)
            response.pipe(localPath)
        });
    }

PS:后面的“J”Date.now()是有意的。

标签: javascriptnode.jstensorflowdiscord.js

解决方案


我看到的是您的应用程序完全不同步 - 我的意思是

你有saveImageToDisk(imageurl,filepath)哪个会将文件写入磁盘,但它会执行,将文件写入队列中,然后你读取(尚未保存)同步文件。

我将尝试对其进行一些修复,以展示至少一种执行此操作的方法 - 但是当您计划应用程序的流程时,您需要考虑代码中的一些同步。

console.log('Authenticating bot...');

const {Client, MessageAttachment} = require('discord.js');
const bot = new Client();
const tf = require('@tensorflow/tfjs-node');
const ts = require('@tensorflow/tfjs-core');
require('@tensorflow/tfjs-backend-cpu');
require('@tensorflow/tfjs-backend-webgl');
const coco = require('@tensorflow-models/coco-ssd');
const fs = require('fs');
const fetch = require("node-fetch");
const https = require('https');
const request = require('request');

bot.login('BOTTOKEN');

bot.on('ready', readyDiscord);

function readyDiscord() {
    console.log('Authenticated and On!');
}

bot.on('message', gotMessage);

async function gotMessage(msg) {
    if(msg.content === '!object')  {   
        const attachments = (msg.attachments).array();

        const filepath = "./images/" + Date.now() + "J" + ".jpg";
        console.log(filepath);
        const imageurl = attachments[0].url;

        await saveImageToDisk(imageurl,filepath)

        const img_buffer = fs.readFileSync(filepath)
        const img = tf.node.decodeImage(img_buffer)

        coco.load().then(model => {
            // detect objects in the image.
            model.detect(img).then(predictions => {
                console.log('Predictions: ', predictions);
            });
          });
        msg.reply('Enjoy');
        msg.channel.send(attachments[0].url);
    }
}
async function saveImageToDisk(url,path) {
  return new Promise((resolve, reject) => {
    var fullUrl = url;
    var localPath = fs.createWriteStream(path);
    var request = https.get(fullUrl,function(response) { 
        console.log(response)
        response.pipe(localPath)
        response.on('end', resolve);
    }).on('error', reject);
  });
}

这样,在执行读取尚未填充文件的代码之前,代码将等待''直到文件被写入(或发生错误) - 你当然应该尝试捕获错误并处理它们。


推荐阅读