Gruntjs 帆上fs.unlinkSync的咕噜声错误

Gruntjs 帆上fs.unlinkSync的咕噜声错误,gruntjs,sails.js,Gruntjs,Sails.js,我使用skipper接收文件,使用sharp调整大小(并保存),使用fs unlink删除旧图像。但这次我犯了一个非常奇怪的错误,这让我很担心: 错误:**Grunt::发生错误** 错误: 由于警告而中止。 正在运行“复制:开发”(复制)任务 警告:无法读取“assets/images/users/c8e303ca-1036-4f52-88c7-fda7e01b6bba.jpg”文件(错误代码:enoint) 错误:看起来发生了咕噜声错误-- 错误:请修复它,然后重新启动Sails以继续运行任

我使用skipper接收文件,使用sharp调整大小(并保存),使用fs unlink删除旧图像。但这次我犯了一个非常奇怪的错误,这让我很担心:

错误:**Grunt::发生错误** 错误: 由于警告而中止。 正在运行“复制:开发”(复制)任务 警告:无法读取“assets/images/users/c8e303ca-1036-4f52-88c7-fda7e01b6bba.jpg”文件(错误代码:enoint)

错误:看起来发生了咕噜声错误-- 错误:请修复它,然后重新启动Sails以继续运行任务(例如,监视资产的变化) 错误:或者如果您被卡住了,请查看下面的故障排除提示

错误:疑难解答提示: 错误: 错误:->“grunt”和相关grunt任务模块是否在本地安装?如果不确定,请运行
npm install
。 错误: 错误:->您可能有格式错误的LESS、SASS、CoffeeScript文件等。 错误: 错误:->或者您没有访问
.tmp
目录的权限? 错误:例如,
(为隐私而编辑)/sails/.tmp
? 错误: 错误:如果您认为可能是这种情况,请尝试运行: 错误:sudo chown-R 1000(为隐私而编辑)/sails/.tmp

Grunt停止了运行,而将其投入生产是一个巨大的挑战。。。我认为这是由于与fs.unlinkSync(fname)并发造成的。该错误也是间歇性的,在某些机器中很难再现(IO操作/秒可能?)

我有以下控制器操作:

var id = 1; // for example

req.file('avatar').upload({
    dirname: require('path').resolve(sails.config.appPath, 'assets/images')
}, function(err, files){
    var avatar = files.pop();

    //file name operations here. output is defined as the path + id + filetype
   //...

    sharp(avatar.fd)
    .resize(800, 800)
    .toFile(output, (err, info)=>{
        if(err){
            res.badRequest();
        } else {
            fs.unlinkSync(avatar.fd);
            res.ok();
        }
    });
});
现在我一直在考虑一些解决方案:

  • 将新图像直接输出到
    .temp
  • .tmp
    上存在文件时取消链接。说明:Grunt已经复制了旧文件,因此删除它是安全的 但我不知道这是不是意大利面代码,甚至不知道是否存在更好的解决方案

    编辑:我的解决方案是,按照arbuthnott的建议,像这样包装一个控制器:

    get : function(req, res){
        var filepath = req.path.slice(1,req.path.length);
        //remove '/' root identifier. path.resolve() could be used
    
        if(fs.existsSync(path.resolve(filepath))){
            return res.sendfile(filepath);
        } else {
            return res.notFound();  
        }
    }
    

    我认为你对这个错误的看法是正确的。您正在对资产文件夹中的进行一些快速更改。如果我读对了你的代码:

  • 将带有用户生成文件名的图像添加到
    资产/images
    (例如
    cat.jpg
  • 将文件复制/调整为
    资产/图像中的id文件名(例如
    abc123.jpg
  • 删除原始上载(
    cat.jpg
  • (我不知道夏普的细节,引擎盖下可能还有更多)

    如果sails在dev模式下运行,那么Grunt将尝试监视整个
    资产/
    文件夹,并将所有更改复制到
    .tmp/public/
    。很容易想象Grunt可能会注册一个更改,但是当它开始复制添加的文件(
    assets/images/cat.jpg
    )时,它已经不存在了


    对于解决方案,我有两个建议:

    一:

    按照您的建议,将您的原件上载到
    .tmp
    文件夹(甚至可能是
    .tmp
    的自定义子文件夹)。仍然将您的大小副本放入
    /assets/images/
    ,它将被复制到
    /.tmp/public/
    ,在那里运行的应用程序可以将其作为资产访问。但是Grunt将忽略
    .tmp
    文件夹中的快速添加然后删除

    二:

    对您希望在版本控制中包含的内容以及您希望在生产中运行的Grunt任务进行一些一般性思考。请注意,如果使用
    sails lift--prod
    ,则默认情况下Grunt watch处于关闭状态,甚至不会发生此错误。一般来说,我觉得我们不希望Grunt在生产中做太多,它更像是一种开发捷径。具体来说,Grunt watch可以使用生产服务器上的大量资源

    关于版本控制的注意事项是,您可能希望
    资产/images/
    的某些内容处于版本控制中(站点使用的图像等),但对于用户上传的头像可能不是这样。确保你有办法区分这些内容(子目录或其他)。然后它们可以很容易地
    .git ignore
    'd或任何合适的东西


    希望这有帮助,祝你好运

    从下到上。我正在为
    assets/images/users/
    .git>中的用户图像制作一个大的bucket文件夹,它忽略了所有内容(除了
    .gitkeep
    )。你在prod中关于Grunt的说法是对的,但我需要手动将每个化身复制到“./tmp”中,然后呢?关于解决方案一,是的,我认为它会起作用。我习惯于将所有非版本控制的媒体保留在资产文件夹之外,并通过
    MediaController
    (使用
    res.sendfile
    )中专门编写的方法过滤所有请求。在某些方面这是一种痛苦,但我们现在已经使用它一年多了,我推荐它。这是一个很好的解决方案,可以隐藏策略等背后的内容。实际上,我正在为受限制的文件这样做。但我认为这是过分简单的图像。。。我不知道,我想我需要花更多的时间来思考这个问题…嘿,只是一个反馈,我做了控制器(这伤了我的心)。现在,它是最好的解决方案,可以避免我在prod中使用Grunt,并且具有良好的文件夹结构。。。它只是一个4线控制器,并且工作正常。蒂阿斯布特诺特!!!伟大的如果你想做一些复杂的事情,比如在媒体上设置策略、允许大小选择、提供备用默认图像等等,你可能会很高兴。正如我所说,我们一年前就开始这样做了,从那以后就再也不需要接触这些方法了。