एक्सप्रेस का उपयोग कर NodeJS सर्वर से एक फ़ाइल डाउनलोड करें


317

मैं एक ऐसी फ़ाइल को कैसे डाउनलोड कर सकता हूं जो किसी नोडज सर्वर में एक पृष्ठ तक पहुंचने वाली मेरी मशीन में मेरे सर्वर में है?

मैं एक्सप्रेसजेएस का उपयोग कर रहा हूं और मैं यह कोशिश कर रहा हूं:

app.get('/download', function(req, res){

  var file = fs.readFileSync(__dirname + '/upload-folder/dramaticpenguin.MOV', 'binary');

  res.setHeader('Content-Length', file.length);
  res.write(file, 'binary');
  res.end();
});

लेकिन मुझे फ़ाइल का नाम और फ़ाइल प्रकार (या एक्सटेंशन) नहीं मिल सकता है। क्या कोई मेरी यह मदद कर सकता है?


13
सिर्फ आपकी जानकारी के लिए। उत्पादन में उपयोग करने के लिए, आप nginx के पीछे n.js का उपयोग करके बेहतर हैं, और nginx को स्थैतिक सामग्री से संभालते हैं। जाहिर है, यह है कि हैंडलिंग के लिए बेहतर अनुकूल है।
मुनीम

3
अप-वोट यह साबित करते हैं कि गूंगे सवाल जैसी कोई बात नहीं है :)
user2180794

2
@ user2180794 लेकिन ऐसी बात है। कई अन्य प्रश्न जो झंडे और नीचे दिए गए हैं, इसका प्रमाण हैं। यह सवाल सबसे निश्चित रूप से एक नहीं है। यह दिशा-निर्देशों से मेल खाता है :)
एसिमिलाटर

आपके द्वारा बताया गया प्रश्न अलग है, यहाँ ओपी एक क्लाइंट को एक फाइल लौटना चाहता है जबकि यह दूसरा सवाल यह है कि क्लाइंट के रूप में अपने सर्वर नोड का उपयोग करके फाइल कैसे डाउनलोड करें (उदाहरण के लिए एक 3 पार्टी से फाइल)। मैं यही समझ रहा हूँ।
एरिक ब्यूरेल

जवाबों:


585

अपडेट करें

जीवन को आसान बनाने के लिए एक्सप्रेस के पास एक सहायक है।

app.get('/download', function(req, res){
  const file = `${__dirname}/upload-folder/dramaticpenguin.MOV`;
  res.download(file); // Set disposition and send it.
});

पुराना उत्तर

जहाँ तक आपके ब्राउज़र का संबंध है, फ़ाइल का नाम सिर्फ 'डाउनलोड' है, इसलिए आपको दूसरे HTTP हेडर का उपयोग करके इसे अधिक जानकारी देने की आवश्यकता है।

res.setHeader('Content-disposition', 'attachment; filename=dramaticpenguin.MOV');

आप इस तरह एक माइम-प्रकार भेजना चाह सकते हैं:

res.setHeader('Content-type', 'video/quicktime');

यदि आप कुछ अधिक गहराई से चाहते हैं, तो यहां जाएं।

var path = require('path');
var mime = require('mime');
var fs = require('fs');

app.get('/download', function(req, res){

  var file = __dirname + '/upload-folder/dramaticpenguin.MOV';

  var filename = path.basename(file);
  var mimetype = mime.lookup(file);

  res.setHeader('Content-disposition', 'attachment; filename=' + filename);
  res.setHeader('Content-type', mimetype);

  var filestream = fs.createReadStream(file);
  filestream.pipe(res);
});

आप जो चाहें वह हेडर मान सेट कर सकते हैं। इस मामले में, मैं माइम-प्रकार पुस्तकालय का उपयोग कर रहा हूं - नोड-माइम , यह जांचने के लिए कि फ़ाइल का माइम-प्रकार क्या है।

यहां ध्यान देने वाली एक और महत्वपूर्ण बात यह है कि मैंने रीडस्ट्रीम का उपयोग करने के लिए आपका कोड बदल दिया है। यह चीजों को करने का एक बेहतर तरीका है क्योंकि नाम में 'सिंक' के साथ किसी भी विधि का उपयोग करने पर इसे फेंक दिया जाता है क्योंकि नोड को अतुल्यकालिक माना जाता है।


3
धन्यवाद .. क्या fs.readFileSync से यह जानकारी प्राप्त करने का कोई तरीका है? मैं इस उदाहरण में एक स्थिर फ़ाइल का उपयोग कर रहा हूं, लेकिन मैं इस डाउनलोड एपीआई का उपयोग किसी भी फाइल के लिए करूंगा, इसका नाम पास कर रहा हूं।
थियागो मिरांडा डे ओलिवेरा

उत्पादन फ़ाइल नाम res.setHeader('Content-disposition', 'attachment; filename=' + filename);tnx के साथ काम करता है की स्थापना !
Capy

कैसे res.download () पद्धति का उपयोग करके कई दस्तावेज़ डाउनलोड करें।
आर। जे।

1
@RJ। यदि आपके पास कोई प्रश्न है, तो एक नया बनाएं, एक टिप्पणी न छोड़ें।
loganfsmyth

7
Btw के .set()बजाय एक्सप्रेस 4.x का उपयोग करता है.setHeader()
दाना वुडमैन

48

उपयोग res.download()

यह फ़ाइल को "अनुलग्नक" के रूप में पथ पर स्थानांतरित करता है। उदाहरण के लिए:

var express = require('express');
var router = express.Router();

// ...

router.get('/:id/download', function (req, res, next) {
    var filePath = "/my/file/path/..."; // Or format the path using the `id` rest param
    var fileName = "report.pdf"; // The default name the browser will use

    res.download(filePath, fileName);    
});

6
क्या होगा यदि डेटा एक फ़ाइल के बजाय एक HTTP अनुरोध से आ रहा था और हमें उपयोगकर्ताओं को फ़ाइल को स्ट्रीमिंग तरीके से डाउनलोड करने देना था?
ग्रीष्मकाल

1
@summerNight - ठीक है, यह निर्दिष्ट प्रश्न की तुलना में एक अलग मामला है। nodejs proxy file download responseसर्वश्रेष्ठ अभ्यास के लिए खोज
जोसेफ हर्ष

15

Pdfs, Word डॉक्स इत्यादि जैसी स्थिर फाइलों के लिए, अपने कॉन्फिगरेशन में एक्सप्रेस के स्थिर फंक्शन का उपयोग करें:

// Express config
var app = express().configure(function () {
    this.use('/public', express.static('public')); // <-- This right here
});

और फिर अपनी सारी फाइलें उस 'सार्वजनिक' फ़ोल्डर के अंदर रख दें, उदाहरण के लिए:

/public/docs/my_word_doc.docx

और फिर एक नियमित पुराना लिंक उपयोगकर्ता को इसे डाउनलोड करने की अनुमति देगा:

<a href="public/docs/my_word_doc.docx">My Word Doc</a>

1
यह परिसंपत्तियों के लिए अच्छी तरह से काम करता है (हालांकि nginx की तरह एक समर्पित सेवारत प्रॉक्सी की सिफारिश की गई है)। लेकिन किसी भी चीज के लिए जिसे सुरक्षित पहुंच की आवश्यकता होती है, स्वीकृत विधि बेहतर है। आम तौर पर डॉक्स और जानकारी युक्त फाइलों के लिए बोलते हुए, मैं सार्वजनिक पद्धति का उपयोग करने की सलाह नहीं दूंगा।
nembleton

1
आप यह सुनिश्चित करने के लिए मिडिलवेयर जोड़ सकते हैं कि केवल उचित उपयोगकर्ता ही फाइलों तक पहुंच
सकें

1
उदा this.use('/topsecret', mGetLoggedInUser, mEnsureAccess, express.static('topsecret'))... और फिर प्रत्येक अनुरोध mEnsureAccess के माध्यम से जाता है। बेशक, इसका मतलब है कि आपको सुरक्षित दस्तावेज़ के url के आधार पर, या जो कुछ भी है, उपयोगकर्ता के एक्सेस स्तर का पता लगाने में सक्षम होना चाहिए।
मैल्कमऑन

14

एक्सप्रेस 4.x में, एक attachment()विधि है Response:

res.attachment();
// Content-Disposition: attachment

res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png

6
'use strict';

var express = require('express');
var fs = require('fs');
var compress = require('compression');
var bodyParser = require('body-parser');

var app = express();
app.set('port', 9999);
app.use(bodyParser.json({ limit: '1mb' }));
app.use(compress());

app.use(function (req, res, next) {
    req.setTimeout(3600000)
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept,' + Object.keys(req.headers).join());

    if (req.method === 'OPTIONS') {
        res.write(':)');
        res.end();
    } else next();
});

function readApp(req,res) {
  var file = req.originalUrl == "/read-android" ? "Android.apk" : "Ios.ipa",
      filePath = "/home/sony/Documents/docs/";
  fs.exists(filePath, function(exists){
      if (exists) {     
        res.writeHead(200, {
          "Content-Type": "application/octet-stream",
          "Content-Disposition" : "attachment; filename=" + file});
        fs.createReadStream(filePath + file).pipe(res);
      } else {
        res.writeHead(400, {"Content-Type": "text/plain"});
        res.end("ERROR File does NOT Exists.ipa");
      }
    });  
}

app.get('/read-android', function(req, res) {
    var u = {"originalUrl":req.originalUrl};
    readApp(u,res) 
});

app.get('/read-ios', function(req, res) {
    var u = {"originalUrl":req.originalUrl};
    readApp(u,res) 
});

var server = app.listen(app.get('port'), function() {
    console.log('Express server listening on port ' + server.address().port);
});

4

यहां बताया गया है कि मैं इसे कैसे करता हूं:

  1. फ़ाइल बनाएँ
  2. ग्राहक को फ़ाइल भेजें
  3. फ़ाइल को हटाएं

कोड:

let fs = require('fs');
let path = require('path');

let myController = (req, res) => {
  let filename = 'myFile.ext';
  let absPath = path.join(__dirname, '/my_files/', filename);
  let relPath = path.join('./my_files', filename); // path relative to server root

  fs.writeFile(relPath, 'File content', (err) => {
    if (err) {
      console.log(err);
    }
    res.download(absPath, (err) => {
      if (err) {
        console.log(err);
      }
      fs.unlink(relPath, (err) => {
        if (err) {
          console.log(err);
        }
        console.log('FILE [' + filename + '] REMOVED!');
      });
    });
  });
};

2
यह एकमात्र ऐसा समाधान है जिसे मैंने खोज के लगभग दो दिनों में पाया है जो ऑडियो फ़ाइल प्राप्त करने के मेरे विशेष परिदृश्य के लिए काम करता है। केवल एक चीज यह है कि मुझे नहीं लगता कि res.download () $ .ajax कॉल के साथ काम करता है। दुर्भाग्य से - मुझे इसका उपयोग करना था window.open("/api/get_audio_file");, देखें: stackoverflow.com/a/20177012
user1063287
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.