Node / Express 파일 업로드


95

저는 노드 v0.10.26과 익스프레스 v4.2.0을 사용하고 있으며 노드에 꽤 익숙합니다. 노드로 작업하는 파일 업로드 양식을 얻으려고 지난 3 시간 동안 책상에 머리를 대고있었습니다. 이 시점에서 나는 undefined를 반환하지 않도록 req.files를 얻으려고합니다. 내 견해는 다음과 같습니다.

<!DOCTYPE html>
<html>
<head>
  <title>{{ title }}</title>
  <link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
  <h1>{{ title }}</h1>
  <p>Welcome to {{ title }}</p>
  <form method='post' action='upload' enctype="multipart/form-data">
    <input type='file' name='fileUploaded'>
    <input type='submit'>
  </form>
</body>
</html>

내 경로는 다음과 같습니다.

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


/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

router.post('/upload', function(req, res){
console.log(req.files);
});

module.exports = router;

그리고 여기 내 app.js가 있습니다.

var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hjs');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});



module.exports = app;

나는 포함 어딘가에 것을보고 methodOverride()bodyParser({keepExtensions:true,uploadDir:path})도움말을했는데하지만 난 그 라인을 추가하면 나는 심지어 내 서버를 시작할 수 없습니다.



4 대신 Express 3을 사용했기 때문에 API가 변경 될 수 있지만 google / bing formidableexpress. AFAIK formiable는 멀티 파트 양식 데이터를 처리하고 파일을 로컬 디스크에 저장 ( uploadDir수단) 한 다음이 req.files를 읽고 비즈니스 로직을 처리 하는 것과 같은 것을 사용할 수 있습니다 .
Shaun Xu

"var bodyParser = require ( 'body-parser');"를 제거하십시오. bodyParser var를 사용하는 대신 다음과 같이 사용합니다. app.use (express.bodyParser ()); app.use (express.methodOverride ()); 이 ATM을 테스트 할 시간이 없습니다 ...
Canastro

늦었지만 미래에 도움이 될 수 있습니다. 다음은 mongodb programmerblog.net/nodejs-file-upload-tutorial을
Jason W

이 라인은 무엇입니까? app.use(express.static(path.join(__dirname, 'public')));
geoidesic

답변:


94

ExpressJS 문제 :

대부분의 미들웨어는 Express 4에서 제거되었습니다. http://www.github.com/senchalabs/connect#middleware busboy, busboy-connect, formidable, flow, parted와 같은 멀티 파트 미들웨어의 경우 필요합니다.

이 예제는 connect-busboy 미들웨어를 사용하여 작동합니다 . / img 및 / public 폴더를 만듭니다.
폴더 구조를 사용하십시오.

\ server.js

\ img \ "자료가 업로드되는 위치"

\ public \ index.html

SERVER.JS

var express = require('express');    //Express Web Server 
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path');     //used for file path
var fs = require('fs-extra');       //File System - for file manipulation

var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));

/* ========================================================== 
Create a Route (/upload) to handle the Form submission 
(handle POST requests to /upload)
Express v4  Route definition
============================================================ */
app.route('/upload')
    .post(function (req, res, next) {

        var fstream;
        req.pipe(req.busboy);
        req.busboy.on('file', function (fieldname, file, filename) {
            console.log("Uploading: " + filename);

            //Path where image will be uploaded
            fstream = fs.createWriteStream(__dirname + '/img/' + filename);
            file.pipe(fstream);
            fstream.on('close', function () {    
                console.log("Upload Finished of " + filename);              
                res.redirect('back');           //where to go next
            });
        });
    });

var server = app.listen(3030, function() {
    console.log('Listening on port %d', server.address().port);
});

INDEX.HTML

<!DOCTYPE html>
<html lang="en" ng-app="APP">
<head>
    <meta charset="UTF-8">
    <title>angular file upload</title>
</head>

<body>
        <form method='post' action='upload' enctype="multipart/form-data">
        <input type='file' name='fileUploaded'>
        <input type='submit'>
 </body>
</html>

다음은 강력한 SERVER.JS에서 작동합니다.

var express = require('express');   //Express Web Server 
var bodyParser = require('body-parser'); //connects bodyParsing middleware
var formidable = require('formidable');
var path = require('path');     //used for file path
var fs =require('fs-extra');    //File System-needed for renaming file etc

var app = express();
app.use(express.static(path.join(__dirname, 'public')));

/* ========================================================== 
 bodyParser() required to allow Express to see the uploaded files
============================================================ */
app.use(bodyParser({defer: true}));
 app.route('/upload')
 .post(function (req, res, next) {

  var form = new formidable.IncomingForm();
    //Formidable uploads to operating systems tmp dir by default
    form.uploadDir = "./img";       //set upload directory
    form.keepExtensions = true;     //keep file extension

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'content-type': 'text/plain'});
        res.write('received upload:\n\n');
        console.log("form.bytesReceived");
        //TESTING
        console.log("file size: "+JSON.stringify(files.fileUploaded.size));
        console.log("file path: "+JSON.stringify(files.fileUploaded.path));
        console.log("file name: "+JSON.stringify(files.fileUploaded.name));
        console.log("file type: "+JSON.stringify(files.fileUploaded.type));
        console.log("astModifiedDate: "+JSON.stringify(files.fileUploaded.lastModifiedDate));

        //Formidable changes the name of the uploaded file
        //Rename the file to its original name
        fs.rename(files.fileUploaded.path, './img/'+files.fileUploaded.name, function(err) {
        if (err)
            throw err;
          console.log('renamed complete');  
        });
          res.end();
    });
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});

35
그래서 우리는 중요한 API를 변경하고 기본적인 것들을 끔찍하게 복잡하게 만드는 프레임 워크를 가지고 있습니다. 그리고 이것이 가장 인기있는 NodeJS 모듈입니까?
wortwart

19
주요 릴리스입니다. semver.org 사양에 따라 주요 릴리스에서 주요 변경 사항이 허용됩니다.
Stuart P. Bentley

6
확실히 semver.org는 주요 버전 번호에서 API 변경을 깨뜨리는 것을 허용하지만, 이는 사용자를 화나게하는 것을 정당화하려는 끔찍한 지점입니다.
joonas.fi

1
Express에서 작업 할 파일 업로드를 얻기 위해 며칠 동안 고군분투했습니다. 감사합니다!!!
aProperFox 2014

1
어, "bodyParser"가 정확히 무엇이며 어디에서 왔습니까? @Mick
로빈

27

또 다른 옵션은 multer 를 사용하는 것입니다.이 방법은 내부에서 busboy 를 사용하지만 설정이 더 간단합니다.

var multer = require('multer');

멀터를 사용하고 업로드 대상을 설정합니다.

app.use(multer({dest:'./uploads/'}));

enctype='multipart/form-data멀터가 작동하려면 보기에서 양식을 작성 해야합니다.

form(role="form", action="/", method="post", enctype="multipart/form-data")
    div(class="form-group")
        label Upload File
        input(type="file", name="myfile", id="myfile")

그런 다음 POST에서 파일에 대한 데이터에 액세스 할 수 있습니다.

app.post('/', function(req, res) {
  console.dir(req.files);
});

이에 대한 전체 자습서는 여기 에서 찾을 수 있습니다 .


4
나는 unknown field오류로 인해 좌절감을 느낀 후 멀터 양식을 옮깁니다 . 내 코드의 모든 것이 정확합니다. 대부분의 경우 작동하며 모든 항목 (환경, 파일, 코드, 파일 이름)이 동일하게 남아있는이 예외를 신비하게 보여줍니다
kishu27

1
throw new TypeError ( 'app.use () requires middleware functions');
크리스

multer 함수를 app.use ```에 전달하는 데 문제가있는 경우 다음과 같이 설정하는 것이 좋습니다. var upload = multer ({dest : 'uploads /'}); var app = express () app.post ( '/ profile', upload.single ( 'field-name'), function (req, res, next) {console.log (req.file);})```
Anibe Agamah

22

다음은 Mick Cullen의 답변에 대한 단순화 된 버전 ( 요점 )입니다 . 부분적으로이를 구현하는 것이 매우 복잡 할 필요는 없음을 증명합니다. 부분적으로는 페이지와 코드 페이지를 읽는 데 관심이없는 사람에게 빠른 참조를 제공합니다.


앱이 connect-busboy를 사용하도록해야합니다 .

var busboy = require("connect-busboy");
app.use(busboy());

트리거 할 때까지 아무것도하지 않습니다. 업로드를 처리하는 호출 내에서 다음을 수행하십시오.

app.post("/upload", function(req, res) {
    if(req.busboy) {
        req.busboy.on("file", function(fieldName, fileStream, fileName, encoding, mimeType) {
            //Handle file stream here
        });
        return req.pipe(req.busboy);
    }
    //Something went wrong -- busboy was not loaded
});

이것을 분해 해보자 :

  • req.busboy가 설정 되었는지 확인합니다 (미들웨어가 올바르게로드되었는지).
  • "file"리스너를 설정했습니다.req.busboy
  • 의 내용 reqreq.busboy

파일 리스너 내부에는 몇 가지 흥미로운 점이 있지만 실제로 중요한 것은 다음과 fileStream같습니다. 이것은 일반적으로 하듯이 파일에 쓸 수 있는 Readable 입니다.

함정 : 이 Readable을 처리해야합니다 . 그렇지 않으면 express가 요청에 응답하지 않습니다 . busboy API ( 파일 섹션)를 참조하십시오 .


21

간단하고 효율적입니다.

const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();

// default options
app.use(fileUpload());

app.post('/upload', function(req, res) {
  if (!req.files || Object.keys(req.files).length === 0) {
    return res.status(400).send('No files were uploaded.');
  }

  // The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
  let sampleFile = req.files.sampleFile;

  // Use the mv() method to place the file somewhere on your server
  sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err) {
    if (err)
      return res.status(500).send(err);

    res.send('File uploaded!');
  });
});

익스프레스 파일 업로드


최신 NPM 패키지로 최신 솔루션을 찾는 사람은 여기를 참조하십시오. express-fileupload는 이것을 정말 쉽게 만듭니다.
jaredbaszler

이 답변은 Github에 제공된 예이지만 저장소 파일을 살펴보면 해당 줄 sampleFile.mv...이 작성 uploadPath = __dirname + '/uploads/' + sampleFile.name;되었음을 알 수 있습니다. 약간의 추가 설명이 도움이된다는 것을 알았습니다. Link
BrettJ

4

제공된 다른 답변보다 조금 더 자세히 설명해야했습니다 (예 : 런타임에 결정한 위치에 파일을 어떻게 작성합니까?). 다른 사람들에게 도움이되기를 바랍니다.  

connect-busboy 가져 오기 :

npm install connect-busboy --save

server.js에서 다음 줄을 추가하십시오.

let busboy = require('connect-busboy')

// ... 

app.use(busboy());

// ... 

app.post('/upload', function(req, res) {
    req.pipe(req.busboy);
    req.busboy.on('file', function(fieldname, file, filename) {
        var fstream = fs.createWriteStream('./images/' + filename); 
        file.pipe(fstream);
        fstream.on('close', function () {
            res.send('upload succeeded!');
        });
    });
});

이것은 오류 처리를 생략하는 것처럼 보일 것입니다 ... 찾으면 편집합니다.


1

Multer는 주로 파일 업로드에 사용되는 multipart / form-data를 처리하기위한 node.js 미들웨어입니다. 최대 효율성을 위해 busboy 위에 작성되었습니다.

npm install --save multer


in app.js

    var multer  =   require('multer');
    var storage = multer.diskStorage({
      destination: function (req, file, callback) {
        callback(null, './public/uploads');
      },
      filename: function (req, file, callback) {
        console.log(file);
        callback(null, Date.now()+'-'+file.originalname)
      }
    });

    var upload = multer({storage: storage}).single('photo');

    router.route("/storedata").post(function(req, res, next){

        upload(req, res, function(err) {
          if(err) {
            console.log('Error Occured');
            return;
          }
          var userDetail = new mongoOp.User({
            'name':req.body.name,
            'email':req.body.email,
            'mobile':req.body.mobile,
            'address':req.body.address
          });

          console.log(req.file);

          res.end('Your File Uploaded');
          console.log('Photo Uploaded');

          userDetail.save(function(err,result){
          if (err) {
            return console.log(err)
          }
          console.log('saved to database') 
        })
      })

      res.redirect('/')

    });

Multer는 주로 파일 업로드에 사용되는 multipart / form-data를 처리하기위한 node.js 미들웨어입니다. 최대 효율성을 위해 busboy 위에 작성되었습니다.
vipinlalrv

더 나은 내가 귀하의 코멘트 섹션과 답변을 편집 한 이해를 위해, 난 당신이 생각하지 않았 으면 : P
Pardeep 자이나교

1

나를 위해 일한 더 쉬운 방법은 다음과 같습니다.

const express = require('express');
var app = express();
var fs = require('fs');

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

  var file = JSON.parse(JSON.stringify(req.files))

  var file_name = file.file.name

  //if you want just the buffer format you can use it
  var buffer = new Buffer.from(file.file.data.data)

  //uncomment await if you want to do stuff after the file is created

  /*await*/
  fs.writeFile(file_name, buffer, async(err) => {

    console.log("Successfully Written to File.");


    // do what you want with the file it is in (__dirname + "/" + file_name)

    console.log("end  :  " + new Date())

    console.log(result_stt + "")

    fs.unlink(__dirname + "/" + file_name, () => {})
    res.send(result_stt)
  });


});

오 와우 흥미로운 구현입니다. 다른 파일 형식에서 잘 작동합니까?
Merunas Grincalaitis 2010 년

0

개인적으로 multer는이 파일 업로드 작업을 올바르게 시도한 후 몇 주 후에 작동하지 않았습니다. 그런 다음 강력한 것으로 전환하고 며칠 후 react가 선택 사항이지만 오류, 여러 파일, express 및 react.js없이 완벽하게 작동합니다. 가이드 : https://www.youtube.com/watch?v=jtCfvuMRsxE&t=122s


0

Node.js Express 및 Typescript를 사용하는 경우 여기에 작동하는 예제가 있습니다. 이것은 자바 스크립트에서도 작동합니다. let을 var로 변경하고 import를 포함하도록 변경하십시오.

먼저 다음 명령을 실행하여 formidable을 설치했는지 확인하십시오.

npm install formidable

다음을 가져 오는 것보다 :

  import * as formidable from 'formidable';
  import * as fs from 'fs';

다음과 같은 기능 :

    uploadFile(req, res) {
    let form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        let oldpath = files.file.path;
        let newpath = 'C:/test/' + files.file.name;
        fs.rename(oldpath, newpath, function (err) {
            if (err) throw err;
            res.write('File uploaded and moved!');
            res.end();
        });
    });
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.