Node.js, Express और Mongoose का उपयोग करके चित्र अपलोड करना


102

कृपया उन नए उत्तरों पर विचार करें जिनमें अधिक अद्यतित जानकारी है क्योंकि पिछले कुछ वर्षों में चीजें बदल गई हैं!

चूंकि कई नई Node.js लाइब्रेरी जल्दी से अप्रचलित हो रही हैं और वैसे भी कुछ उदाहरण हैं जो मैं उन छवियों के बारे में अपलोड करना चाहता हूं:

  • Node.js (v0.4.1)
  • एक्सप्रेस (1.0.7)
  • मोंगोज़ (1.1.0)।

दूसरों ने कैसे किया है?

मैंने पाया है: नोड-दुर्जेय , लेकिन मैं सामान्य रूप से चित्र अपलोड करने के लिए नया हूं इसलिए मैं Node.js और एक्सप्रेस का उपयोग करके सामान्य सामान और ऐसा करने के तरीके सीखना चाहता हूं।


12
एक्सप्रेस के अद्यतन नए संस्करणों में यह कार्यक्षमता अंतर्निहित है, इस पर विचार करें कि 'कनेक्ट-फॉर्म' के साथ समय बिताने से पहले
user531694

4
2015 tl; dr- अपने सर्वर के लिए मल्टीपार्ट / फॉर्म रिक्वेस्ट भेजें और उन्हें मुलर के साथ पार्स करें क्योंकि बॉडीपेयर अब पार्स फाइल नहीं करता है। npm install multer --saveऔर फिर अपने ऐप में आप एक्सेस कर सकते हैं req.files.your_file_param_nameऔर या तो s3 के साथ सेव कर सकते हैं aws-sdkयाfs.writeFile(...)
उपयोगकर्ता

जवाबों:


74

मैं पहली बार अपने सवाल का जवाब दूंगा। मुझे एक उदाहरण सीधे स्रोत से मिला। कृपया गरीबों का इंडेंटेशन माफ करें। मुझे यकीन नहीं था कि नकल और चिपकाने के दौरान ठीक से कैसे इंडेंट करें। कोड GitHub पर एक्सप्रेस multipart/form-dataउदाहरण से सीधे आता है।

// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');

/**
 * Module dependencies.
 */

var express = require('../../lib/express')
  , form = require('connect-form');

var app = express.createServer(
  // connect-form (http://github.com/visionmedia/connect-form)
  // middleware uses the formidable middleware to parse urlencoded
  // and multipart form data
  form({ keepExtensions: true })
);

app.get('/', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Image: <input type="file" name="image" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});

app.post('/', function(req, res, next){

  // connect-form adds the req.form object
  // we can (optionally) define onComplete, passing
  // the exception (if any) fields parsed, and files parsed
  req.form.complete(function(err, fields, files){
    if (err) {
      next(err);
    } else {
      console.log('\nuploaded %s to %s'
        ,  files.image.filename
        , files.image.path);
      res.redirect('back');
    }
  });

  // We can add listeners for several form
  // events such as "progress"
  req.form.on('progress', function(bytesReceived, bytesExpected){
    var percent = (bytesReceived / bytesExpected * 100) | 0;
    process.stdout.write('Uploading: %' + percent + '\r');
  });
});

app.listen(3000);
console.log('Express app started on port 3000');

3
हाँ, लेकिन आप फ़ाइल को कैसे सहेजते हैं?
निक रिटलैक

1
@NickRetallack सहेजी गई फ़ाइल files.image.path पर संग्रहीत की जाती है
रॉबिन डकेट

@ रॉबिन-डकेट, आपने पहले से फ़ाइल नाम और पथ कैसे निर्दिष्ट किया?
ल्यूक

4
@Luc: आप ऐसा नहीं करते हैं, यह एक अस्थायी निर्देशिका में सहेजा जाता है, जहाँ से आप इसे कहीं और स्थानांतरित करते हैं।
केवमो 314

1
यह है कि आप एक्सप्रेस निर्देशिका को एक्सप्रेस में कैसे कॉन्फ़िगर करते हैं: // नोट: सबमोडुल्स में समस्याओं से बचने के लिए अपलोड निर्देशिका के लिए एक निरपेक्ष पथ का उपयोग करें! // app.use (express.bodyParser ({uploadDir: uploadDir}));
ऋषिदिन

47

चूंकि आप एक्सप्रेस का उपयोग कर रहे हैं, बस बॉडीपेयर जोड़ें:

app.use(express.bodyParser());

तब आपके मार्ग में स्वचालित रूप से req.files में अपलोड की गई फ़ाइल तक पहुंच है:

app.post('/todo/create', function (req, res) {
    // TODO: move and rename the file using req.files.path & .name)
    res.send(console.dir(req.files));  // DEBUG: display available fields
});

यदि आप इस तरह (जेड में) इनपुट नियंत्रण "टूडू" का नाम देते हैं:

form(action="/todo/create", method="POST", enctype="multipart/form-data")
    input(type='file', name='todo')
    button(type='submit') New

तब अपलोड की गई फ़ाइल तब तक तैयार हो जाती है जब तक आपको 'files.todo' में पथ और मूल फ़ाइल नाम नहीं मिल जाता है:

  • req.files.todo.path, और
  • req.files.todo.name

अन्य उपयोगी req.files गुण:

  • आकार (बाइट्स में)
  • प्रकार (जैसे, 'छवि / पीएनजी')
  • lastModifiedate
  • _writeStream.encoding (जैसे, 'बाइनरी')

मैंने कभी नहीं सुना कि इसे इस तरह से संदर्भित किया जाए और मैं आगे जाऊंगा और कहूंगा कि ये लोग सबसे अच्छे से जानते हैं डेवलपर. हैं; इसलिए मुझे लगता है कि हम दोनों गलत हैं;)
सरकिन

bodyParserअसुरक्षित है, कम से कम इसके अनुसार: andrewkelley.me/post/do-not-use-bodyparser-with-express-js.htmlजॉन जे के जवाब ने मेरे लिए काम किया।
मैट ब्राउन

"असुरक्षित" द्वारा, इसका मतलब है कि अस्थायी फाइलें बनाई गई हैं, ताकि एक "हमले" संभवतः अस्थायी फाइलों के साथ सर्वर के डिस्क स्थान को भर सके। यह अधिक मजबूती वाला मुद्दा है, क्योंकि यह सुरक्षा छेद नहीं है।
ब्रेंट फस्ट

19

आप अपनी मुख्य एप्लिकेशन फ़ाइल में कॉन्फ़िगरेशन ब्लॉक में कनेक्ट बॉडी पार्सर मिडलवेयर को कॉन्फ़िगर कर सकते हैं:

    /** Form Handling */
    app.use(express.bodyParser({
        uploadDir: '/tmp/uploads',
        keepExtensions: true
    }))
    app.use(express.limit('5mb'));

यह वास्तव में मुझे लगता है अपलोड अपलोड करने का सबसे अच्छा तरीका है। यदि आप किसी अन्य स्थान पर कॉपी करना चाहते हैं, तो फ़ाइल को अलग रखें। धन्यवाद।
पूर्वी भिक्षु

2
@ अक्षरप्रभुदेसाई हां और नहीं। कहते हैं कि आपके पास एक फोटो अपलोड / फसल उपकरण है। यदि आप उपयोगकर्ता को अपने सार्वजनिक फ़ोल्डर में सीधे अपलोड करने की अनुमति देते हैं, तो आपके पास एक गंभीर सुरक्षा दोष है। इस स्थिति में, tmp फ़ोल्डर में अपलोड करना और फ़ाइल की पुष्टि करने के बाद अपने सार्वजनिक फ़ोल्डर में ले जाना एक ट्रोजन नहीं है।
सरकिन

अब समर्थित नहीं लगता है। एक अच्छा समाधान की तरह लग रहा था।
ब्लेज़

14

देखें, आप जो सबसे अच्छी चीज कर सकते हैं, वह है बस छवि को डिस्क पर अपलोड करना और MongoDB में URL को सहेजना। आराम करें जब आप छवि को फिर से प्राप्त करते हैं। बस URL निर्दिष्ट करें, और आपको एक छवि मिलेगी। अपलोड करने के लिए कोड इस प्रकार है।

app.post('/upload', function(req, res) {
    // Get the temporary location of the file
    var tmp_path = req.files.thumbnail.path;
    // Set where the file should actually exists - in this case it is in the "images" directory.
    target_path = '/tmp/' + req.files.thumbnail.name;
    // Move the file from the temporary location to the intended location
    fs.rename(tmp_path, target_path, function(err) {
        if (err)
            throw err;
        // Delete the temporary file, so that the explicitly set temporary upload dir does not get filled with unwanted files.
        fs.unlink(tmp_path, function() {
            if (err)
                throw err;
            //
        });
    });
});

अब अपने MongoDB डेटाबेस में लक्ष्य पथ को सहेजें।

फिर से, छवि को पुनः प्राप्त करते समय, बस MongoDB डेटाबेस से URL निकालें, और इस पद्धति पर इसका उपयोग करें।

fs.readFile(target_path, "binary", function(error, file) {
    if(error) {
        res.writeHead(500, {"Content-Type": "text/plain"});
        res.write(error + "\n");
        res.end();
    }
    else {
        res.writeHead(200, {"Content-Type": "image/png"});
        res.write(file, "binary");
    }
});

9

इस कोड को आज़माएं। यह मदद करेगा।

app.get('/photos/new', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Data: <input type="filename" name="filename" /></p>'
    + '<p>file: <input type="file" name="file" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});


 app.post('/photos/new', function(req, res) {
  req.form.complete(function(err, fields, files) {
    if(err) {
      next(err);
    } else {
      ins = fs.createReadStream(files.photo.path);
      ous = fs.createWriteStream(__dirname + '/directory were u want to store image/' + files.photo.filename);
      util.pump(ins, ous, function(err) {
        if(err) {
          next(err);
        } else {
          res.redirect('/photos');
        }
      });
      //console.log('\nUploaded %s to %s', files.photo.filename, files.photo.path);
      //res.send('Uploaded ' + files.photo.filename + ' to ' + files.photo.path);
    }
  });
});

if (!module.parent) {
  app.listen(8000);
  console.log("Express server listening on port %d, log on to http://127.0.0.1:8000", app.address().port);
}

util.pump(ins, ous)मूल्यह्रास किया गया है, यह ins.pipe(ous);अब के साथ किया जा सकता है । लेकिन क्या यह पुराने स्थान पर छवि फ़ाइल को हटा देगा?
एमियल वांडेनबसचे

8

आप पथ को सेट करने के लिए निम्न का उपयोग भी कर सकते हैं जहां यह फ़ाइल को बचाता है।

req.form.uploadDir = "<path>";

5

मैंने एक उदाहरण बनाया जो एक्सप्रेस और मुल्टर का उपयोग करता है। यह बहुत सरल है और सभी कनेक्ट चेतावनियों से बचा जाता है

यह किसी की मदद कर सकता है।


1
इसके लिए धन्यवाद। यह पूर्ण, अप-टू-डेट उदाहरणों का पता लगाना मुश्किल है, bodyParserजो उपयोग नहीं करते हैं (जो असुरक्षित है, देखें andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html )
मैट ब्राउन

2

यदि आप bodyParser का उपयोग नहीं करना चाहते हैं, तो निम्नलिखित कार्य करता है:

var express = require('express');
var http = require('http');
var app = express();

app.use(express.static('./public'));


app.configure(function(){
    app.use(express.methodOverride());
    app.use(express.multipart({
        uploadDir: './uploads',
        keepExtensions: true
    }));
});


app.use(app.router);

app.get('/upload', function(req, res){
    // Render page with upload form
    res.render('upload');
});

app.post('/upload', function(req, res){
    // Returns json of uploaded file
    res.json(req.files);
});

http.createServer(app).listen(3000, function() {
    console.log('App started');
});

2

एक्सप्रेस 3.0 के लिए, यदि आप दुर्जेय घटनाओं का उपयोग करना चाहते हैं, तो आपको मल्टीपार्ट मिडलवेयर को हटाना होगा, ताकि आप इसके नए उदाहरण बना सकें।

यह करने के लिए:

app.use(express.bodyParser());

के रूप में लिखा जा सकता है:

app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart()); // Remove this line

और अब फॉर्म ऑब्जेक्ट बनाएं:

exports.upload = function(req, res) {
    var form = new formidable.IncomingForm;
    form.keepExtensions = true;
    form.uploadDir = 'tmp/';

    form.parse(req, function(err, fields, files){
        if (err) return res.end('You found error');
        // Do something with files.image etc
        console.log(files.image);
    });

    form.on('progress', function(bytesReceived, bytesExpected) {
        console.log(bytesReceived + ' ' + bytesExpected);
    });

    form.on('error', function(err) {
        res.writeHead(400, {'content-type': 'text/plain'}); // 400: Bad Request
        res.end('error:\n\n'+util.inspect(err));
    });
    res.end('Done');
    return;
};

मैंने इसे अपने ब्लॉग पर भी पोस्ट 3.0 में अपलोड पर दुर्जेय रूप वस्तु के रूप में पोस्ट किया है ।


आपका सुझाव भ्रामक है, बॉडीपार मूल रूप से फॉर्म को पार्स करता है। और दुर्जेय विन्यास चर को स्वीकार करता है।
मारियस

1
@timoxley यह केवल उदाहरण है
Risto Novik

1

मुझे पता है कि विशिष्ट संस्करणों से संबंधित मूल प्रश्न, लेकिन यह "नवीनतम" के लिए भी संदर्भित है - @JohnAllen का पोस्ट अब एक्सप्रेसज बॉडीपार और कनेक्ट-फॉर्म के कारण प्रासंगिक नहीं है

यह निर्मित बॉडीपार () का उपयोग करने के लिए आसान दर्शाता है:

 /**
 * Module dependencies.
 */

var express = require('express')

var app = express()
app.use(express.bodyParser({ keepExtensions: true, uploadDir: '/home/svn/rest-api/uploaded' }))

app.get('/', function(req, res){
  res.send('<form method="post" enctype="multipart/form-data">'
    + '<p>Image: <input type="file" name="image" /></p>'
    + '<p><input type="submit" value="Upload" /></p>'
    + '</form>');
});

app.post('/', function(req, res, next){

    res.send('Uploaded: ' + req.files.image.name)
    return next()

});

app.listen(3000);
console.log('Express app started on port 3000');

0

एकाधिक अपलोड फ़ाइल में मेरी विधि है:

नोडज:

router.post('/upload', function(req , res) {

var multiparty = require('multiparty');
var form = new multiparty.Form();
var fs = require('fs');

form.parse(req, function(err, fields, files) {  
    var imgArray = files.imatges;


    for (var i = 0; i < imgArray.length; i++) {
        var newPath = './public/uploads/'+fields.imgName+'/';
        var singleImg = imgArray[i];
        newPath+= singleImg.originalFilename;
        readAndWriteFile(singleImg, newPath);           
    }
    res.send("File uploaded to: " + newPath);

});

function readAndWriteFile(singleImg, newPath) {

        fs.readFile(singleImg.path , function(err,data) {
            fs.writeFile(newPath,data, function(err) {
                if (err) console.log('ERRRRRR!! :'+err);
                console.log('Fitxer: '+singleImg.originalFilename +' - '+ newPath);
            })
        })
}
})

सुनिश्चित करें कि आपके फॉर्म में enctype = "मल्टीपार्ट / फॉर्म-डेटा" है

मुझे आशा है कि यह आपको एक हाथ देता है;)


0

यहां दुर्जेय पैकेज का उपयोग करके अपनी छवियों को अपलोड करने का एक तरीका है, जिसे एक्सप्रेस के बाद के संस्करणों में बॉडीपार पर अनुशंसित किया गया है। इसमें मक्खी पर अपनी छवियों को आकार देने की क्षमता भी शामिल है:

मेरी वेबसाइट से: Node.js और एक्सप्रेस के साथ छवियाँ अपलोड करना और आकार देना (मक्खी पर)

यहाँ है जिस्ट:

var express = require("express"),
app = express(),
formidable = require('formidable'),
util = require('util')
fs   = require('fs-extra'),
qt   = require('quickthumb');

// Use quickthumb
app.use(qt.static(__dirname + '/'));

app.post('/upload', function (req, res){
  var form = new formidable.IncomingForm();
  form.parse(req, function(err, fields, files) {
    res.writeHead(200, {'content-type': 'text/plain'});
    res.write('received upload:\n\n');
    res.end(util.inspect({fields: fields, files: files}));
  });

  form.on('end', function(fields, files) {
    /* Temporary location of our uploaded file */
    var temp_path = this.openedFiles[0].path;
    /* The file name of the uploaded file */
    var file_name = this.openedFiles[0].name;
    /* Location where we want to copy the uploaded file */
    var new_location = 'uploads/';

    fs.copy(temp_path, new_location + file_name, function(err) {  
      if (err) {
        console.error(err);
      } else {
        console.log("success!")
      }
    });
  });
});

// Show the upload form 
app.get('/', function (req, res){
  res.writeHead(200, {'Content-Type': 'text/html' });
  /* Display the file upload form. */
  form = '<form action="/upload" enctype="multipart/form-data" method="post">'+ '<input name="title" type="text" />
  '+ '<input multiple="multiple" name="upload" type="file" />
  '+ '<input type="submit" value="Upload" />'+ '</form>';
  res.end(form); 
}); 
app.listen(8080);

ध्यान दें: इसके लिए त्वरित अंगूठे के आकार के लिए इमेज मैजिक की आवश्यकता होती है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.