[Image] 使用node.js下載圖像


Answers

前幾天我遇到了這個問題,對於純粹的NodeJS答案,我建議使用Stream將塊合併在一起。

var http = require('http'),                                                
    Stream = require('stream').Transform,                                  
    fs = require('fs');                                                    

var url = 'http://www.google.com/images/srpr/logo11w.png';                    

http.request(url, function(response) {                                        
  var data = new Stream();                                                    

  response.on('data', function(chunk) {                                       
    data.push(chunk);                                                         
  });                                                                         

  response.on('end', function() {                                             
    fs.writeFileSync('image.png', data.read());                               
  });                                                                         
}).end();

最新的Node版本對於二進製字符串不能很好地工作,因此在處理二進制數據時將塊與字符串合併不是一個好主意。

*使用'data.read()'時要小心,它會清空下一個'read()'操作的流。 如果您想多次使用它,請將其存儲在某個地方。

Question

我正在嘗試編寫一個腳本來使用node.js下載圖像。 這是我到目前為止:

var maxLength = 10 // 10mb
var download = function(uri, callback) {
  http.request(uri)
    .on('response', function(res) {
      if (res.headers['content-length'] > maxLength*1024*1024) {
        callback(new Error('Image too large.'))
      } else if (!~[200, 304].indexOf(res.statusCode)) {
        callback(new Error('Received an invalid status code.'))
      } else if (!res.headers['content-type'].match(/image/)) {
        callback(new Error('Not an image.'))
      } else {
        var body = ''
        res.setEncoding('binary')
        res
          .on('error', function(err) {
            callback(err)
          })
          .on('data', function(chunk) {
            body += chunk
          })
          .on('end', function() {
            // What about Windows?!
            var path = '/tmp/' + Math.random().toString().split('.').pop()
            fs.writeFile(path, body, 'binary', function(err) {
              callback(err, path)
            })
          })
      }
    })
    .on('error', function(err) {
      callback(err)
    })
    .end();
}

然而,我想讓這更強大:

  1. 有沒有圖書館這樣做,並做得更好?
  2. 有沒有機會回應標題(關於長度,關於內容類型)?
  3. 還有我應該關心的其他狀態代碼嗎? 我應該打擾重定向嗎?
  4. 我想我在某處讀到binary編碼將被棄用。 那我該怎麼做?
  5. 我怎樣才能讓它在windows上工作?
  6. 任何其他方法可以使這個腳本更好?

為什麼:對於類似於imgur的功能,用戶可以給我一個URL,我下載該圖像,並以多種尺寸重新映像圖像。




如果你想進度下載試試這個:

var fs = require('fs');
var request = require('request');
var progress = require('request-progress');

module.exports = function (uri, path, onProgress, onResponse, onError, onEnd) {
    progress(request(uri))
    .on('progress', onProgress)
    .on('response', onResponse)
    .on('error', onError)
    .on('end', onEnd)
    .pipe(fs.createWriteStream(path))
};

如何使用:

  var download = require('../lib/download');
  download("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png", "~/download/logo.png", function (state) {
            console.log("progress", state);
        }, function (response) {
            console.log("status code", response.statusCode);
        }, function (error) {
            console.log("error", error);
        }, function () {
            console.log("done");
        });

注意:您應該使用以下命令安裝請求和請求進度模塊:

npm install request request-progress --save