Sails上fs.unlinkSync的Grunt错误

时间:2017-11-30 13:34:24

标签: gruntjs sails.js

我正在使用skipper接收文件,使用sharp来调整大小(并保存)和fs取消链接以删除旧图像。但是这次我得到了一个非常奇怪的错误,这让我很担心:

  

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

     

错误:看起来发生了Grunt错误 -   错误:请修复它,然后重新启动Sails 以继续运行任务(例如,观察资产的变化)   错误:或者如果您遇到困难,请查看下面的问题排查提示。

     

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

Grunt停止运行并且在生产中使用它是一个很大的NoNo ...我认为这是由于fs.unlinkSync(fname)的并发性造成的。错误也是间歇性的,很难在某些机器上重现(IO ops / sec可能?)。

我有以下控制器操作:

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();
        }
    });
});

现在我一直在考虑一些解决方案:

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

    编辑:我的解决方案是,如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();  
        }
    }
    

1 个答案:

答案 0 :(得分:1)

我认为你在关于错误的正确轨道上。您正在资产文件夹中进行一些快速更改。如果我正确阅读你的代码:

  1. 将包含用户生成的文件名的图片添加到assets/images(ex cat.jpg
  2. 将文件复制/调整为assets/images中的id文件名(ex abc123.jpg
  3. 删除原始上传(cat.jpg
  4. (我不知道尖锐的细节,那里可能还有更多的东西)

    如果sails正在开发模式下运行,那么Grunt将尝试观看整个assets/文件夹,并将所有更改复制到.tmp/public/。很容易想象Grunt可以注册一个更改,但是当它复制添加的文件(assets/images/cat.jpg)时,它已经消失了。

    我对解决方案有两点建议:

    一:

    与您建议的一样,将您的原始文件上传到.tmp文件夹(甚至可能是.tmp的自定义子文件夹)。仍然将您的大小的副本放入/assets/images/,然后将其复制到/.tmp/public/,以便运行的应用可以将其作为资产进行访问。但Grunt将忽略.tmp文件夹中的快速添加 - 删除。

    二:

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

    关于版本控制的说明只是您可能希望assets/images/的某些内容处于版本控制(网站使用的图像等),但可能不是用户上传的头像的情况。确保您有办法区分这些内容(子目录或其他)。然后,他们可以很容易.git-ignore或其他任何适当的。

    希望这有帮助,祝你好运!