首页 > 解决方案 > NodeJS 本身在 Windows 上保存文件 EBUSY?

问题描述

我创建了一个简单的函数来处理上传的文件。我正在使用 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);
}

标签: node.jsfs

解决方案


原来缩略图创建者锐利是问题所在,如this github issue中所述。

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

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

推荐阅读