Express를 사용하여 NodeJS 서버에서 파일 다운로드


318

서버에있는 파일을 nodeJS 서버의 페이지에 액세스하는 시스템으로 다운로드하려면 어떻게해야합니까?

ExpressJS를 사용하고 있으며 이것을 시도했습니다.

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 뒤에 node.js를 사용하고 nginx가 정적 컨텐츠를 처리하도록하는 것이 좋습니다. 분명히, 그것을 처리하는 데 훨씬 더 적합합니다.
Munim

3
업 - 투표는 그런 일이 :) 바보 같은 질문으로이 없다는 것을 증명
user2180794

2
@ user2180794 그러나 그런 것이 있습니다. 깃발을 달고 투표를하는 다른 많은 질문들이 그 증거입니다. 이 질문은 가장 확실하지 않습니다. 그것은 지침과 일치합니다 :)
Assimilater

OP가 지적한 질문은 다릅니다. 여기서 OP는 파일을 클라이언트에 반환하려고하지만이 다른 질문은 서버 노드를 클라이언트로 사용하여 파일을 다운로드하는 방법에 관한 것입니다 (예 : 타사의 파일). 적어도 내가 이해 한 것입니다.
Eric Burel

답변:


586

최신 정보

Express 삶을 더 편하게 해주는 도우미 입니다.

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

다음과 같은 MIME 유형을 보낼 수도 있습니다.

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

헤더 값을 원하는대로 설정할 수 있습니다. 이 경우 파일의 MIME 유형이 무엇인지 확인하기 위해 MIME 유형 라이브러리-node-mime을 사용하고 있습니다.

여기서 주목해야 할 또 다른 중요한 것은 readStream을 사용하도록 코드를 변경했다는 것입니다. 노드가 비동기식이기 때문에 이름에 '동기화'가있는 메소드를 사용하는 것이 싫기 때문에이 방법이 훨씬 더 나은 방법입니다.


3
감사합니다. fs.readFileSync에서이 정보를 얻는 방법이 있습니까? 이 예제에서는 정적 파일을 사용하고 있지만 모든 파일에이 다운로드 API를 사용하여 이름을 전달합니다.
Thiago Miranda de Oliveira

출력 파일 이름 설정은 res.setHeader('Content-disposition', 'attachment; filename=' + filename);tnx 와 함께 작동합니다 !
Capy

res.download () 메소드를 사용하여 여러 문서를 다운로드하는 방법
R J.

1
@RJ. 질문이 있으면 새로운 질문을 작성하고 의견을 남기지 마십시오.
loganfsmyth

7
Express 4.x는 btw .set()대신 사용.setHeader()
Dana Woodman

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 요청에서 데이터가 들어오고 사용자가 스트리밍 방식으로 파일을 다운로드 할 수있게하려면 어떻게해야합니까?
summerNight

1
@summerNight-글쎄, 그것은 지정된 질문과 다른 경우입니다. nodejs proxy file download response모범 사례 검색
Jossef Harush

15

PDF, Word 문서 등과 같은 정적 파일의 경우 구성에서 Express의 정적 기능을 사용하십시오.

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

그런 다음 모든 파일을 해당 'public'폴더에 넣으십시오.

/public/docs/my_word_doc.docx

그런 다음 일반 이전 링크를 통해 사용자가 다운로드 할 수 있습니다.

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

1
그것은 자산에 잘 작동합니다 (nginx와 같은 전용 서빙 프록시가 권장되지만). 그러나 안전한 액세스가 필요한 모든 경우 허용되는 방법이 더 좋습니다. 일반적으로 정보가 포함 된 문서 및 파일을 말하면 공개 방법을 사용하지 않는 것이 좋습니다.
nembleton 2016 년

1
적절한 사용자 만 파일에 액세스 할 수 있도록 미들웨어를 추가 할 수 있습니다.
MalcolmOcean

1
예를 들어 this.use('/topsecret', mGetLoggedInUser, mEnsureAccess, express.static('topsecret'))... 각 요청은 mEnsureAccess를 거치게됩니다. 물론 보안 문서의 URL 등을 기반으로 사용자의 액세스 수준을 파악할 수 있어야합니다.
MalcolmOcean

14

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

5

내가하는 방법은 다음과 같습니다.

  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
이것은 오디오 파일을 얻는 특정 시나리오에서 작동하는 약 2 일간의 검색에서 찾은 유일한 솔루션입니다. 유일한 것은 내가 생각하지 않는다는 것입니다 ) (res.download를 작동 $ 아약스 불행하게도 전화 - 내가 사용했다 window.open("/api/get_audio_file");참조 : stackoverflow.com/a/20177012
user1063287
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.