Express kullanarak NodeJS Sunucusundan dosya indirme


318

Bir nodeJS sunucusundaki bir sayfaya erişerek sunucumdaki bir dosyayı makineme nasıl indirebilirim?

ExpressJS kullanıyorum ve bunu deniyorum:

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

Ancak dosya adını ve dosya türünü (veya uzantısını) alamıyorum. Biri bana bununla ilgili yardım edebilir mi?


13
Sadece FYI. Üretimde kullanmak için, nginx'in arkasında node.js kullanmaktan daha iyidir ve nginx'in statik içeriği işlemesini sağlarsınız. Görünüşe göre, bunu ele almak için çok daha uygun.
Munim

3
Yukarı oylar aptalca bir soru diye bir şey olmadığını kanıtlıyor :)
user2180794

2
@ user2180794 ama böyle bir şey var. İşaretlenen ve aşağı oy kullanan diğer birçok soru bunun kanıtıdır. Bu soru kesinlikle bir soru değil. Bu kurallara uygundur :)
Assimilater

İşaret ettiğiniz soru farklıdır, burada OP bir istemciye bir dosya döndürmek isterken, diğer soru sunucu Düğümünüzü bir istemci olarak nasıl indireceğinizle ilgilidir (örneğin 3. bir taraftan bir dosya). Lesast'ta bunu anladım.
Eric Burel

Yanıtlar:


586

Güncelleme

Express'in hayatı kolaylaştırmak için bir yardımcısı vardır .

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

Eski Cevap

Tarayıcınızla ilgili olarak, dosyanın adı sadece 'indir' dir, bu nedenle başka bir HTTP başlığı kullanarak daha fazla bilgi vermeniz gerekir.

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

Bunun gibi bir mim türü de göndermek isteyebilirsiniz:

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

Daha derinlemesine bir şey istiyorsanız, işte buradasınız.

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

Üstbilgi değerini istediğiniz gibi ayarlayabilirsiniz. Bu durumda, dosyanın mime türünün ne olduğunu denetlemek için bir mime türü kitaplığı - düğüm-mime kullanıyorum .

Burada dikkat edilmesi gereken bir diğer önemli şey, bir readStream kullanmak için kodunuzu değiştirmiş olmasıdır. Bu, işleri yapmanın çok daha iyi bir yoludur çünkü adda 'Senkronizasyon' ile herhangi bir yöntem kullanıldığında, düğümün eşzamansız olması gerektiği için kaşlarını çatmıştır.


3
Teşekkürler .. Bu bilgiyi fs.readFileSync'ten almanın bir yolu var mı? Bu örnekte statik bir dosya kullanıyorum, ancak bu indirme API'sini herhangi bir dosya için adını geçerek kullanacağım.
Thiago Miranda de Oliveira

Çıktı dosya res.setHeader('Content-disposition', 'attachment; filename=' + filename);adını ayarlamak tnx ile çalışır !
Capy

res.download () yöntemini kullanarak birden çok belgeyi indirme.
R J.

1
@RJ. Bir sorunuz varsa, yeni bir soru oluşturun, yorum bırakmayın.
loganfsmyth

7
Express 4.x btw .set()yerine kullanır.setHeader()
Dana Woodman

48

kullanım res.download()

Yoldaki dosyayı “ek” olarak aktarır. Örneğin:

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
Veriler dosya yerine bir HTTP isteğinden geliyorsa ve kullanıcıların dosyayı akış yoluyla indirmesine izin vermeliydik?
summerGece

1
@summerNight - bu, belirtilen sorudan farklı bir durum. nodejs proxy file download responseuygulama için arama yap
Jossef Harush

15

Pdfs, Word belgeleri vb. Gibi statik dosyalar için, yapılandırmanızda Express'in statik işlevini kullanın:

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

Ve sonra tüm dosyalarınızı bu 'genel' klasörün içine koyun, örneğin:

/public/docs/my_word_doc.docx

Ve sonra normal bir eski bağlantı kullanıcının indirmesine izin verecektir:

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

1
Bu, varlıklar için iyi çalışır (nginx gibi özel bir sunum proxy'si önerilmesine rağmen). Ancak güvenli erişim gerektiren her şey için kabul edilen yöntem daha iyidir. Genel olarak bilgi içeren dokümanlar ve dosyalar için genel yöntemi kullanmanızı tavsiye etmem.
nembleton

1
dosyalara yalnızca uygun kullanıcıların erişebilmesini sağlamak için ara katman yazılımı ekleyebilirsiniz
MalcolmOcean

1
örneğin this.use('/topsecret', mGetLoggedInUser, mEnsureAccess, express.static('topsecret'))... ve sonra her istek mEnsureAccess üzerinden geçer. Tabii ki bu, bir kullanıcının erişim düzeyini, yalnızca güvenli belgenin URL'sine veya başka bir şeye dayanarak anlayabilmeniz gerektiği anlamına gelir.
MalcolmOcean

14

Express 4.x'te aşağıdakileri yapmak için bir attachment()yöntem vardır 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);
});

5

İşte nasıl yaparım:

  1. dosya oluştur
  2. istemciye dosya gönder
  3. dosyayı kaldır

Kod:

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
Bu bir ses dosyası almak benim özel senaryo için çalışan arama yaklaşık iki gün içinde bulduk tek çözümdür. tek şey, res.download () $ .ajax çağrıları ile ne yazık ki çalıştığını sanmıyorum - kullanmak zorunda kaldım window.open("/api/get_audio_file");, bkz: stackoverflow.com/a/20177012
user1063287 14:19
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.