Düğüm / Ekspres dosya yükleme


96

V0.10.26 düğümünü kullanıyorum ve v4.2.0'ı ifade ediyorum ve düğümde oldukça yeniyim. Node ile çalışan bir dosya yükleme formu almaya çalışırken son üç saattir kafamı masama vuruyorum. Bu noktada sadece req. Dosyalarının tanımsız olarak dönmemesi için çalışıyorum. Benim görüşüm buna benziyor

<!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>

İşte rotalarım

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;

Ve işte benim 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;

Bunu içeren methodOverride()ve bodyParser({keepExtensions:true,uploadDir:path})yardımcı olması gereken bir yer gördüm , ancak bu satırları eklersem sunucumu bile başlatamam.



4 yerine ekspres 3 kullandım, bu yüzden api'si değişebilir, ancak bence google / bing formidableve express. AFAIK'i etkinleştirmeniz gerekir, formiablehangisi çok parçalı form verileriyle ilgilenmekten sorumlu olur, dosyaları yerel diske kaydedin (bu uploadDiryöntemdir), ardından req.filesbunları okumak ve iş mantığınızı işlemek gibi bir şey kullanabilirsiniz .
Shaun Xu

"Var bodyParser = require ('body-parser');" öğesini kaldırmayı deneyin. ve bu bodyParser varlığını kullanmak yerine şuna benzer bir şey kullanın: app.use (express.bodyParser ()); app.use (express.methodOverride ()); Bu
atm'yi

Geç kaldı ama gelecekte birileri için faydalı olabilir. Burada mongodb programmerblog.net/nodejs-file-upload-tutorial
Jason W

Bu hat ne için? app.use(express.static(path.join(__dirname, 'public')));
geoidesic

Yanıtlar:


94

ExpressJS Sorunu:

Ara yazılımların çoğu ekspres 4'ten kaldırılır. Şu adrese bakın : http://www.github.com/senchalabs/connect#middleware Busboy, busboy-connect, müthiş, akış, parted gibi çok parçalı ara yazılımlar için gereklidir.

Bu örnek, connect-busboy ara yazılımını kullanarak çalışır . / img ve / public klasörler oluşturun.
Klasör yapısını kullanın:

\ server.js

\ img \ "öğelerin yüklendiği yer"

\ 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>

Aşağıdakiler zorlu SERVER.JS ile çalışacaktır.

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
Dolayısıyla, hayati API'leri değiştiren ve temel şeyleri korkunç derecede karmaşık hale getiren bir çerçevemiz var. Ve bu en popüler NodeJS modülü?
wortwart

19
Bu büyük bir sürüm. Semver.org spesifikasyonuna göre ana sürümlerde ara değişikliklere izin verilir.
Stuart P. Bentley

6
Tabii semver.org, büyük sürüm numaralarındaki API değişikliklerini kırmaya izin veriyor, ancak bu, kullanıcılarınızı kızdırmayı haklı çıkarmaya çalışırken korkunç bir nokta.
joonas.fi

1
Express ile çalışmak için dosya yüklemek için günlerdir mücadele ediyorum. Teşekkür ederim!!!
aProperFox

1
Ee, "bodyParser" tam olarak nedir ve nereden gelir? @Mick
Robin

27

Diğer bir seçenek ise , kaputun altında garson kullanan, ancak kurulumu daha basit olan sap parçalayıcı kullanmaktır .

var multer = require('multer');

Düzenleyiciyi kullanın ve yükleme için hedefi ayarlayın:

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

Görünümünüzde bir form oluşturun, enctype='multipart/form-dataparçalayıcının çalışması için gereklidir:

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

Ardından POST'unuzda dosya hakkındaki verilere erişebilirsiniz:

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

Bununla ilgili tam bir eğitim burada bulunabilir .


4
Hatayla hayal kırıklığına uğradıktan sonra form parçalayıcıdan uzaklaşıyorum unknown field. Kodumdaki her şey doğru. Çoğu zaman işe yarıyor ve sonra aynı kalan her şeyle (ortam, dosya, kod, dosya adı) bu istisnayı gizemli bir şekilde gösteriyor
kishu27

1
yeni TypeError ('app.use () ara yazılım işlevleri gerektirir');
kris

Parçalayıcı işlevini app.use `` var upload = multer ({dest: 'uploads /'}); var app = express () app.post ('/ profile', upload.single ('alan-adı'), işlev (req, res, next) {console.log (req. dosya);}) ``
Anibe Agamah

22

İşte Mick Cullen'ın yanıtının basitleştirilmiş bir versiyonu ( özü ) - kısmen bunu uygulamanın çok karmaşık olmasına gerek olmadığını kanıtlamak için; kısmen sayfaları ve kod sayfalarını okumakla ilgilenmeyenler için hızlı bir referans vermek için.


Uygulamanızı connect-busboy kullanmalısınız :

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

Bu, siz onu tetikleyene kadar hiçbir şey yapmaz. Yüklemeyi yöneten çağrı içinde aşağıdakileri yapın:

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

Bunu parçalayalım:

  • req.busboyAyarlanıp ayarlanmadığını kontrol edin (ara yazılım doğru şekilde yüklendi)
  • Bir "file"dinleyici kurarsınızreq.busboy
  • Seni boru içerikleri reqiçinreq.busboy

Dosya dinleyicisinin içinde birkaç ilginç şey vardır, ancak asıl önemli olan şudur fileStream: bu bir Okunabilirdir , daha sonra genellikle yaptığınız gibi bir dosyaya yazılabilir.

Tuzak: Bu Okunabilir işlemek veya isteğe yanıt asla ifade edilmelidir , bkz komi API ( dosya bölümü).


22

Bunu basit ve etkili buluyorum:

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

hızlı dosya yükleme


Güncel bir NPM paketi ile daha yeni bir çözüm arayan biri buraya bakmalıdır. ekspres dosya yükleme işlemi bunu gerçekten kolaylaştırır.
jaredbaszler

Bu cevap, Github'da verilen örnektir, ancak depo dosyalarına baktığınızda, satırın sampleFile.mv...yazıldığını görüyorsunuz uploadPath = __dirname + '/uploads/' + sampleFile.name;- bu küçük ekstra açıklamayı yararlı buldum Link
BrettJ

4

Sağlanan diğer yanıtlardan biraz daha ayrıntılı olarak dolaşılmam gerekiyordu (örneğin, dosyayı çalışma zamanında karar verdiğim bir konuma nasıl yazabilirim?). Umarım bu başkalarına yardımcı olur:  

bağlan-busboy olsun:

npm install connect-busboy --save

Server.js dosyanıza şu satırları ekleyin

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

Bu, hata işlemeyi ihmal ediyor gibi görünse de ... bulursam içinde düzenleyecektir.


1

Multer, çok parçalı / form verilerini işlemeye yönelik bir node.js ara yazılımıdır ve esas olarak dosyaları yüklemek için kullanılır. Maksimum verim için garsonun üstüne yazılmıştır.

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, çok parçalı / form verilerini işlemeye yönelik bir node.js ara yazılımıdır ve esas olarak dosyaları yüklemek için kullanılır. Maksimum verimlilik için garsonun üzerine yazılmıştır.
vipinlalrv

daha iyi anlamak için yorum bölümünüzle cevabınızı düzenledim, umarım aldırmazsınız: P
Pardeep Jain

1

İşte benim için işe yarayan daha kolay bir yol:

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


});

oh vay bu ilginç bir uygulama. Farklı dosya formatları için iyi çalışıyor mu?
Merunas Grincalaitis

0

Şahsen multer, bu dosya yükleme işini doğru yapmaya çalıştıktan haftalar sonra benim için işe yaramadı. Sonra müthişe geçiyorum ve birkaç gün sonra herhangi bir hatasız, birden çok dosya, express ve react.js, react isteğe bağlı olmasına rağmen mükemmel şekilde çalışmasını sağladım. İşte kılavuz: https://www.youtube.com/watch?v=jtCfvuMRsxE&t=122s


0

Node.js Express ve Typescript kullanıyorsanız burada çalışan bir örnek var, bu javascript ile de çalışır, sadece let'i var'a ve içe aktarmayı içerir vb. Olarak değiştirin.

ilk önce aşağıdakileri içe aktarın, aşağıdaki komutu çalıştırarak müthiş kurduğunuzdan emin olun:

npm install formidable

aşağıdakileri içe aktarmak yerine:

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

sonra feryat gibi fonksiyonunuz:

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