【问题标题】:NodeJS itself keeps file EBUSY on Windows?NodeJS 本身在 Windows 上保存文件 EBUSY?
【发布时间】:2019-06-18 19:57:26
【问题描述】:

我创建了一个简单的函数来处理上传的文件。我正在使用 multer 将多部分数据处理成文件。然后我使用下面的代码来移动文件,并返回数据,以便我的网页知道如何显示图像。

似乎 NodeJS 以某种方式使文件保持打开状态。我还创建了一个删除文件的函数,但这会给我一个 EBUSY 错误。如果我尝试通过 Windows 删除,它会说 NodeJS 已锁定文件。当我重新启动 NodeJS 进程,然后重新请求删除 URL 时,文件被正确删除。

有什么方法可以强制 NodeJS 关闭文件资源吗?或者我的脚本中是否还有其他一些我遗漏的错误?

我将节点更新到 12.4.0 版,但这也没有帮助。

处理上传:

exports.handleFormNotes = async(req, res, next) => {
    try {
        const configVariables = req.app.get('configVariables');
        const uploadSuffix = req.body.uploadFolderSuffix || '';

        console.log('upload suffix', uploadSuffix);

        if (!req.files.length) {
            return;
        }

        const uploadedFiles = Array();

        var destPath = configVariables['FormNotesUploadDirectory'];
        if (uploadSuffix !== '') 
            destPath = destPath + '/' + uploadSuffix;
        destPath = path.resolve(destPath);

        // mkdirSync returns undefined, so run that first and see if the directory exists second.
        if (!fs.mkdirSync(destPath, { recursive: true }) && !fs.existsSync(destPath)) {
            console.log(destPath, 'does not exist!');
            req.alertHandler.addAlert('Pad om afbeelding op te slaan is niet bereikbaar: ' + destPath, 'danger');
            res.render('error');
            return;
        }

        var baseUrlPath = configVariables['FormNotesUploadDocumentRoot'];
        if (uploadSuffix != null) {
            baseUrlPath = baseUrlPath + '/' + uploadSuffix;
        }

        for(const uploadedFile of req.files) {
            let now = new Date();
            let destFilename = getDateTime() + "_" + uploadedFile.originalname;
            let destFilenameThumb = 'thumb_' + destFilename;

            var fullDestination = path.resolve(destPath + '/' + destFilename);
            var fullDestinationThumb = path.resolve(destPath + '/' + destFilenameThumb);

            console.log('Copy src:', uploadedFile.path, fullDestination);
            fs.copyFileSync(uploadedFile.path, fullDestination);

            var unlinkResult = fs.unlinkSync(uploadedFile.path);
            console.log('Unlink "' + uploadedFile.path + '", result after upload:', unlinkResult);

            var newFileInfo = await sharp(destPath + '/' + destFilename)
                .resize({ width: 120 })
                .toFile(fullDestinationThumb);

            console.log('new file info thumb:', newFileInfo);

            uploadedFiles.push({
                'fullImg': baseUrlPath + '/' + destFilename,
                'thumbImg' : baseUrlPath + '/' + destFilenameThumb,
                'original': uploadedFile.originalname
            });
        }

        // Push to backend
        const data = {
            files: [...uploadedFiles],
            uploadSuffix: uploadSuffix
        };

        // Normally retVal should be the return data from OI. If anything goes wrong, retVal = 'error'
        this.saveAttachment(req, res, data);
        return res.send(data);    
    }
    catch (err) {
        console.log('Error handling from notes:', err);
        req.alertHandler.addAlert('Error handling form notes: ' + err);
        return 'error';
    }
}

删除上传:

exports.rmFormNote = async(req, res, data) => {
    let retVal;

    try {
        const configVariables = req.app.get('configVariables');

        const httpPath = req.query.img;
        console.log('http path:', httpPath);

        // Strip off the document root, but check if they are the same first
        const firstPart = httpPath.substring(0, configVariables['FormNotesUploadDocumentRoot'].length);

        console.log('same?', firstPart, configVariables['FormNotesUploadDocumentRoot']);
        var relPath = httpPath;
        if (firstPart == configVariables['FormNotesUploadDocumentRoot']) {
            relPath = httpPath.substring(configVariables['FormNotesUploadDocumentRoot'].length + 1);
        }

        var parts = relPath.split('/');
        parts[parts.length-1] = 'thumb_' + parts[parts.length-1];
        var thumbPath = parts.join('/');
        thumbPath = path.resolve(configVariables['FormNotesUploadDirectory'] + '/' + thumbPath);

        console.log('thumbpath: ', thumbPath);

        var fullPath = configVariables['FormNotesUploadDirectory'] + '/' + relPath;
        var dest = path.resolve(fullPath);

        console.log('dest: ', dest);


        if (!fs.existsSync(dest)) 
            throw "File not found";

        fs.unlink(dest, (err) => {
            if (err) throw err;
            console.log('File deleted');
        });

        retVal = { result: true };
    }
    catch(err) {
        console.log('Ohnoo', err);

        retVal = { result: false, msg: err };

    }

    return res.send(retVal);
}

【问题讨论】:

  • 您在上面的代码中混合了同步和异步功能。由于fs.unlink 是一个异步函数,您必须从该函数的回调中返回响应。如果您不想在此处修改整个代码,则可以改用fs.unlinksync。但是,如果您在生产中使用如此繁重的同步函数,您将遇到性能问题。
  • 你是对的;我尝试使用 fs.unlink 看看这是否会使事情变得更好。它没有。回到 fs.unlinkSync 我仍然遇到同样的问题。

标签: node.js fs


【解决方案1】:

事实证明,缩略图创建者锐利是问题所在,如this github issue 所述。

我只需要禁用缓存,如下所示:

sharp.cache(false);
var newFileInfo = await sharp(destPath + '/' + destFilename)
    .resize({ width: 120 })
    .toFile(fullDestinationThumb);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-02
    • 2023-01-21
    • 1970-01-01
    • 2019-09-15
    • 2018-06-30
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多