2017-11-30 11 views
1

私はファイルを受け取るためにスキッパーを使用しています。シャープを使用してサイズ変更(および保存)し、fsリンクを解除して古いイメージを削除しています。しかし、私は非常に奇妙なエラーに私をたくさん懸念今回得た:帆上のfs.unlinkSyncのグランターエラー

error: ** Grunt :: An error occurred. ** error: Aborted due to warnings. Running "copy:dev" (copy) task Warning: Unable to read "assets/images/users/c8e303ca-1036-4f52-88c7-fda7e01b6bba.jpg" file (Error code: ENOENT).

error: Looks like a Grunt error occurred-- error: Please fix it, then restart Sails to continue running tasks (e.g. watching for changes in assets) error: Or if you're stuck, check out the troubleshooting tips below.

error: Troubleshooting tips: error: error: *-> Are "grunt" and related grunt task modules installed locally? Run npm install if you're not sure. error: error: *-> You might have a malformed LESS, SASS, CoffeeScript file, etc. error: error: *-> Or maybe you don't have permissions to access the .tmp directory? error: e.g., (edited for privacy)/sails/.tmp ? error: error: If you think this might be the case, try running: error: sudo chown -R 1000 (edited for privacy)/sails/.tmp

うなり声が実行を停止し、生産に大きなNoいいえであることを持っているが...私はこれが原因で、FSと並行処理で引き起こされると信じています。 unlinkSync(fname)。また、エラーは間欠的で、一部のマシンでは再現するのが非常に難しい(IO ops /秒かもしれない?)。

I以下のコントローラのアクションがあります。今

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はすでに古いファイルをコピーしていますので、削除すると安全です!

しかし、これがスパゲッティコードなのか、より良い解決策があるのか​​わかりません。

EDIT:

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

私はあなたがエラーに関する正しい軌道に乗っていると思う:私のソリューションは、arbuthnottによって提案されたように、このようなコントローラをラップしました。あなたはassetsフォルダ内をすばやく変更しています。私はあなたのコードの右読めば:

  1. assets/imagesにユーザーが生成したファイル名で画像を追加します(例:cat.jpg
  2. コピー/ assets/images(EX abc123.jpg
  3. を削除して、IDファイル名にファイルのサイズを変更元のアップロード(cat.jpg

(私はシャープの詳細を知らない、そこにボンネットの下に多くのがあるかもしれない)

セイルがdevモードで実行されている場合、グランツはassets/フォルダ全体を見て、すべての変更を.tmp/public/にコピーしようとしています。 Gruntが変更を登録するかもしれないと想像するのは簡単ですが、追加されたファイル(assets/images/cat.jpg)をコピーすることになると、既に消えてしまいます。


私は解決策のための2つの提案があります:あなたは.tmpフォルダ(.tmpの多分カスタムサブフォルダ)にあなたの元をアップロードし、提案のように

ワン。あなたのサイズのコピーを/assets/images/に入れて、実行中のアプリでアセットとしてアクセスできる/.tmp/public/にコピーします。しかし、Gruntは、.tmpフォルダのadd-then-deleteを無視します。

2:

は何をバージョン管理に含めると、どのようなうなり声タスク本番で実行されているしたいの両方に関する一般的な思考のビットを行います。 sails lift --prodを使用した場合、Grunt watchはデフォルトではオフになっており、このエラーは発生しません。一般的に、私はグランツがプロダクションであまりにも多くのことをしたいとは思わない、それは開発のショートカットの多くです。具体的には、Gruntウォッチは運用サーバー上で多くのリソースを使用できます。

バージョンコントロールに関する注釈は、assets/images/のコンテンツの一部をバージョン管理(サイトで使用されているイメージなど)にしたいと思っているだけですが、ユーザーがアップロードしたアバターの場合はそうでないかもしれません。これらのコンテンツ(サブディレクトリなど)を区別する方法があることを確認してください。その後、彼らは簡単に.git-ignore 'dまたは適切なことができます。

これは、幸運を助けることを願っています!

+0

下から上へ。私は 'assets/images/users /'と '' .gitignoring "'( '.gitkeep'を除いて)のユーザ画像用の大きなバケツフォルダを作っています。あなたはGruntについて知りましたが、手作業で各アバターを './tmp'にコピーする必要がありますか? 解決策1については、ええ、私はそれがトリックを行うと思います。 – paulogdm

+0

私は資産管理フォルダの外にバージョン管理されていないすべてのメディアを保管し、 'res.sendfile'を使用して' MediaController'に書かれた特別な方法ですべてのリクエストをフィルタリングするという習慣を得ました。それはいくつかの点で痛みですが、今は1年以上使っています。私はそれをお勧めします。 – arbuthnott

+0

これは、ポリシーなどの背後にあるものを隠すための良い解決策です。私は実際に制限されたファイルに対してこれをやっています。しかし、私はそれが単純なイメージに残酷だと思う...私は、私はこれについて考えてもっと多くの時間を費やす必要があると思います... – paulogdm