masalibの日記

システム開発、運用と猫の写真ブログです

node.jsでURL(image系)の存在チェック

経緯

本来ありえないけど、イメージファイルが存在しない場合に200ステータスのごめんなさいページ(HTML)をかえすサーバーがあった
これだと本当に画像が存在しないのかはwgetでは判断できなかった
対応して事前に存在チェックすることにした

仕様

headリクエストをして、responseのHeaderのcontents-typeで判断することにした
もしファイルが存在しない場合は下記のように処理した

もし最初の拡張子がgifなら jpg → png の順でチェックする
もし最初の拡張子がjpgなら png → gif の順でチェックする
もし最初の拡張子がpngなら jpg → gif の順でチェックする
もし最初の拡張子が上記以外なら 空白or 該当の拡張子,jpg → png → .gifの順番でチェックする

前作業

asyncのモジュールをインストールする
このモジュールは標準では入っていないらしい

$ sudo npm install async 

チェックする関数

/**
 * URLの画像が存在しているのか確認
 * @param {string} target_url:ダウンロード対象のURL
 * @param {string} fn:コールバック関数
 */
function checkurl(rtarget_url, fn) {
	console.log('chcekurl:' + rtarget_url)
	//headリクエストになっている
	request.head(rtarget_url, function(err, res, body) {
	  if (err) {
		fn(new Error(  ('Error: ' + err.message)  )   );
	    return ;
	  }
	  console.log('statusCode: ' + res.statusCode)
	  if (res.statusCode == '200') {
		  console.log('headers:');
		  for (var key in res.headers) {
			if (key == 'content-type'){
			    //console.log('  ' + key + ': ' + res.headers[key]);
				if (res.headers[key] == 'image/gif'){
					fn();
					return 
				} else if(res.headers[key] == 'image/jpg'){
					fn();
					return 
				} else if(res.headers[key] == 'image/jpeg'){
					fn();
					return 
				} else if(res.headers[key] == 'image/png'){
					fn();
					return 
				} else {
					fn(new Error(  ('Error: ' + 'content-type: ' + res.headers[key])  )   );
					return 
				}
			}

		  }
			fn(new Error(  ('Error: ' + 'content-type:nothing' )  )   );
			return 


	  } else {
		fn(new Error(  ('Error: ' + 'statusCode: ' + res.statusCode)  )   );
	    return ;
	  }

	});

チェックする関数を呼び出す側

非同期でおこなうとおかしくなったので同期で回すことにした

var request = require('request');
var path = require('path');
var async = require('async');	//標準ではないので「npm i async」でインストールする

targeturl = 'https://hogehoge.com/xxxxxxxxxxxx11x1/xxxx111111111111'

successtargeturl = ''
console.log('targeturl:' + targeturl)
var ext = path.extname(targeturl);
var bsname = path.basename(targeturl, ext);

var targeturl_noext = path.dirname(targeturl) + '/';
console.log('targeturl_noext:' + targeturl_noext)	//拡張子なしバージョン
console.log('bsname:' + bsname)	//拡張子なしバージョン
console.log('ext:' + ext)		//拡張子

if (ext == '.jpg') {
	var chkext = ['.jpg','.png','.gif'];
} else if (ext == '.png') {
	var chkext = ['.png','.jpg','.gif'];
} else if (ext == '.gif') {
	var chkext = ['.gif','.jpg','.png'];
} else {
	var chkext = [ext,'.jpg','.png','.gif'];
}
console.log('chkext:' + chkext)		//チェックしていく拡張子が配列にはいったのか確認

console.log("-- Waterfall check start ----------");
//同期で回している所
async.forEachSeries(chkext, function(val, cb) {
	if (successtargeturl == '') {
		checkurl(targeturl_noext + bsname + val,  function(err){
			if(err){
			    console.log('Error');
				cb();
			} else {
			    console.log('seccess');
				if (successtargeturl == '') {
					successtargeturl = targeturl_noext + bsname + val; 
				}
				cb();
			}
		});
	} else {
		cb();
	}

}, function() {
  console.log("-- Waterfall check end ----------");
  console.log('successtargeturl' +successtargeturl);
});

感想

同期と非同期の処理を意識しないと処理がおかしくなってしまう
色々な開発をおこなって、判断を早くしていきたい

参考URL

ありがとうございます

HTTP通信やURLの部分
info-i.net
maku77.github.io

ループの部分
chaika.hatenablog.com
qiita.com

Node.js超入門

Node.js超入門