नोड.जेएस के साथ चित्र डाउनलोड करना [बंद]


169

मैं एक स्क्रिप्ट लिखने की कोशिश कर रहा हूँ नोड ।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. मैं इसे विंडोज़ पर काम करने के लिए कैसे प्राप्त कर सकता हूं?
  6. किसी भी अन्य तरीके से आप इस स्क्रिप्ट को बेहतर बना सकते हैं?

Why: imgur जैसी सुविधा के लिए जहां उपयोगकर्ता मुझे एक URL दे सकते हैं, मैं उस छवि को डाउनलोड करता हूं, और छवि को कई आकारों में पुनः सेट करता हूं।

जवाबों:


401

मैं अनुरोध मॉड्यूल का उपयोग करने का सुझाव दूंगा । फ़ाइल डाउनलोड करना निम्न कोड की तरह सरल है:

var fs = require('fs'),
    request = require('request');

var download = function(uri, filename, callback){
  request.head(uri, function(err, res, body){
    console.log('content-type:', res.headers['content-type']);
    console.log('content-length:', res.headers['content-length']);

    request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
  });
};

download('https://www.google.com/images/srpr/logo3w.png', 'google.png', function(){
  console.log('done');
});

1
ठंडा! क्या वास्तव में इसे डाउनलोड करने से पहले आकार और सामग्री प्रकार की जांच करने का कोई तरीका है?
जोनाथन ओंग

2
यह छवियों को कहाँ से डाउनलोड करता है?
गोफिलॉर्ड

17
मेरे लिए काम नहीं कर रहा है (छवि दूषित
डार्थ

2
@ Gofilord इसकी डाउनलोड छवि को आपकी रूट डायरेक्टरी में ले जाता है।
खतरे

1
क्या आप उस स्थान को बदल सकते हैं जहां वे सहेजे गए हैं? यदि आप उन्हें एक विशिष्ट फ़ोल्डर में चाहते थे?
AKL012

34

मैं कुछ दिन पहले इस समस्या में भाग गया था, एक शुद्ध NodeJS उत्तर के लिए मैं चंचल को एक साथ मर्ज करने के लिए स्ट्रीम का उपयोग करने का सुझाव दूंगा।

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

नवीनतम नोड संस्करण बाइनरी स्ट्रिंग्स के साथ अच्छी तरह से काम नहीं करेंगे, इसलिए बाइनरी डेटा के साथ काम करते समय स्ट्रिंग्स के साथ मर्जिंग एक अच्छा विचार नहीं है।

* 'Data.read ()' का उपयोग करते समय बस सावधान रहें, यह अगले 'रीड ()' ऑपरेशन के लिए स्ट्रीम को खाली कर देगा। यदि आप इसे एक से अधिक बार उपयोग करना चाहते हैं, तो इसे कहीं स्टोर करें।


7
सीधे डिस्क पर डाउनलोड को स्ट्रीम क्यों नहीं किया?
जियोन

यह एक भ्रष्ट फ़ाइल बनाई के रूप में एक साथ तार
झनझनाहट के

27

आप एसिंक्रोनस वातावरण में अपने चयन के क्रम में छवियों को डाउनलोड करने के लिए Axios ( Node.js के लिए एक वादा- आधारित HTTP क्लाइंट) का उपयोग कर सकते हैं :

npm i axios

फिर, आप छवियों को डाउनलोड करने के लिए निम्नलिखित मूल उदाहरण का उपयोग कर सकते हैं:

const fs = require('fs');
const axios = require('axios');

/* ============================================================
  Function: Download Image
============================================================ */

const download_image = (url, image_path) =>
  axios({
    url,
    responseType: 'stream',
  }).then(
    response =>
      new Promise((resolve, reject) => {
        response.data
          .pipe(fs.createWriteStream(image_path))
          .on('finish', () => resolve())
          .on('error', e => reject(e));
      }),
  );

/* ============================================================
  Download Images in Order
============================================================ */

(async () => {
  let example_image_1 = await download_image('https://example.com/test-1.png', 'example-1.png');

  console.log(example_image_1.status); // true
  console.log(example_image_1.error); // ''

  let example_image_2 = await download_image('https://example.com/does-not-exist.png', 'example-2.png');

  console.log(example_image_2.status); // false
  console.log(example_image_2.error); // 'Error: Request failed with status code 404'

  let example_image_3 = await download_image('https://example.com/test-3.png', 'example-3.png');

  console.log(example_image_3.status); // true
  console.log(example_image_3.error); // ''
})();

2
महान उदाहरण! लेकिन मुश्किल से पठनीय कोड, मानक शैली का प्रयास करें : D
Camwhite

3
@camwhite मुझे अर्धविराम पसंद हैं । ;)
ग्रांट मिलर

1
आपको वास्तव में really फिनिश ’और 'एरर’ इवेंट्स को राइट स्ट्रीम में अटैच करना चाहिए, उन्हें एक प्रॉमिस में लपेटें और वादा वापस करें। अन्यथा आप एक ऐसी छवि का उपयोग करने का प्रयास कर सकते हैं जो अभी तक पूरी तरह से डाउनलोड नहीं हुई है।
जेवर में

इंतजार नहीं करना सुनिश्चित करेगा कि छवि डाउनलोड पूरी तरह से उपयोग करने की कोशिश कर रही है? @jwerre
FabricioG

@jwerre @FabricioG download_imageने लौटाए गए वादे के लिए 'फिनिश' और 'एरर' इवेंट को कैप्चर करने के लिए फंक्शन को अपडेट किया है
बेनो तुंग

10

यदि आप प्रगति डाउनलोड करना चाहते हैं तो यह कोशिश करें:

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

2
इसने बहुत अच्छा काम किया, लेकिन एक statusCodeचेक जोड़ने का सुझाव देना चाहता था । उदाहरण के लिए एक 500 स्टेटसकोड, हिट नहीं होगा 'on("error", e)on('response', (response) => console.error(response.statusCode))इसे जोड़ने से बहुत डिबगिंग की सुविधा मिलती है,
mateuscb

1
आप मेरे उत्तर को संपादित कर सकते हैं :)
फरीद अलमृतौटी

4

उपरोक्त निर्माण, अगर किसी को लिखने / पढ़ने की धाराओं में त्रुटियों को संभालने की आवश्यकता है, तो मैंने इस संस्करण का उपयोग किया। stream.read()लेखन त्रुटि के मामले में ध्यान दें , यह आवश्यक है ताकि हम रीडिंग को पूरा कर सकें और closeरीड स्ट्रीम पर ट्रिगर कर सकें ।

var download = function(uri, filename, callback){
  request.head(uri, function(err, res, body){
    if (err) callback(err, filename);
    else {
        var stream = request(uri);
        stream.pipe(
            fs.createWriteStream(filename)
                .on('error', function(err){
                    callback(error, filename);
                    stream.read();
                })
            )
        .on('close', function() {
            callback(null, filename);
        });
    }
  });
};

2
stream.read()पुराना प्रतीत होता है, एक त्रुटि फेंकता हैnot a function
बेंडुलम

4
var fs = require('fs'),
http = require('http'),
https = require('https');

var Stream = require('stream').Transform;

var downloadImageToUrl = (url, filename, callback) => {

    var client = http;
    if (url.toString().indexOf("https") === 0){
      client = https;
     }

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

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

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

downloadImageToUrl('https://www.google.com/images/srpr/logo11w.png', 'public/uploads/users/abc.jpg');

1
अपने कार्य कॉलबैक ट्रिगर नहीं करता
crockpotveggies

4

यह सीज़री के उत्तर का विस्तार है। यदि आप इसे किसी विशिष्ट निर्देशिका में डाउनलोड करना चाहते हैं, तो इसका उपयोग करें। इसके अलावा, var के बजाय const का उपयोग करें। इस तरह से यह सुरक्षित है।

const fs = require('fs');
const request = require('request');
var download = function(uri, filename, callback){
  request.head(uri, function(err, res, body){    
    request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
  });
};

download('https://www.google.com/images/srpr/logo3w.png', './images/google.png', function(){
  console.log('done');
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.