Unggahan file node / Express

96

Saya menggunakan node v0.10.26 dan express v4.2.0 dan saya cukup baru mengenal node. Saya telah memukuli kepala saya ke meja saya selama tiga jam terakhir atau lebih mencoba untuk mendapatkan formulir unggahan file yang bekerja dengan node. Pada titik ini saya hanya mencoba untuk mendapatkan req.files agar tidak mengembalikan undefined. Pandangan saya terlihat seperti ini

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

Ini rute saya

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;

Dan inilah app.js saya

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;

Saya melihat suatu tempat yang termasuk methodOverride()dan bodyParser({keepExtensions:true,uploadDir:path})seharusnya membantu tetapi saya bahkan tidak dapat meluncurkan server saya jika saya menambahkan baris tersebut.

okawei
sumber
Saya menggunakan express 3 bukan 4 jadi apinya mungkin berubah, tapi saya pikir Anda perlu google / bing formidabledan express. AFAIK Anda perlu mengaktifkan formiableyang mengambil tanggung jawab untuk menangani data bentuk multipart, menyimpan file di disk lokal (yang uploadDirartinya) kemudian Anda dapat menggunakan sesuatu seperti req.filesuntuk membacanya dan memproses logika bisnis Anda.
Shaun Xu
Coba hapus "var bodyParser = require ('body-parser');" dan alih-alih menggunakan var bodyParser, gunakan sesuatu seperti ini: app.use (express.bodyParser ()); app.use (express.methodOverride ()); Saya tidak punya waktu untuk menguji atm ini ...
Canastro
ini terlambat tetapi mungkin berguna untuk seseorang di masa depan. Berikut adalah tutorial lengkap upload file node js dengan program
Jason W
Untuk apa baris ini? app.use(express.static(path.join(__dirname, 'public')));
geoidesic

Jawaban:

94

Masalah ExpressJS:

Sebagian besar middleware dihapus dari express 4. Lihat: http://www.github.com/senchalabs/connect#middleware Untuk middleware multipart seperti busboy, busboy-connect, tangguh, flow, parted diperlukan.

Contoh ini bekerja menggunakan middleware connect-busboy . buat / img dan / folder publik.
Gunakan struktur folder:

\ server.js

\ img \ "tempat barang diunggah ke"

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

Berikut ini akan bekerja dengan SERVER.JS yang tangguh

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);
});
Mick Cullen
sumber
35
Jadi kami memiliki kerangka kerja yang mengubah API penting dan membuat hal-hal dasar menjadi sangat rumit. Dan itu adalah modul NodeJS yang paling populer?
wortwart
19
Ini rilis utama. Perubahan yang melanggar diizinkan dalam rilis utama sesuai spesifikasi semver.org.
Stuart P. Bentley
6
Tentu semver.org memungkinkan pemutusan perubahan API dalam nomor versi utama, tetapi itu adalah poin yang mengerikan dalam mencoba membenarkan membuat marah pengguna Anda.
joonas.fi
1
Saya telah berjuang selama berhari-hari untuk mengupload file agar berfungsi dengan cepat. Terima kasih!!!
aProperFox
1
Eh, sebenarnya apa itu "bodyParser" dan darimana asalnya? @Mick
Robin
27

Pilihan lainnya adalah menggunakan multer , yang menggunakan busboy di bawah kap, tetapi lebih sederhana untuk dipasang.

var multer = require('multer');

Gunakan multer dan tetapkan tujuan untuk mengunggah:

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

Buat formulir dalam tampilan Anda, enctype='multipart/form-datadiperlukan agar multer berfungsi:

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

Kemudian di POST Anda, Anda dapat mengakses data tentang file:

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

Tutorial lengkapnya dapat ditemukan di sini .

Carasel
sumber
4
Saya pindah dari multer setelah frustrasi dengan unknown fieldkesalahan. Semua yang ada di kode saya benar. Ini berfungsi sebagian besar waktu kemudian secara misterius menunjukkan pengecualian ini dengan segala sesuatu yang tetap sama (lingkungan, file, kode, nama file)
kishu27
1
membuang TypeError baru ('app.use () membutuhkan fungsi middleware');
keris
Anda mungkin ingin menyiapkan seperti ini jika Anda mengalami masalah dengan meneruskan fungsi multer ke 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

Ini adalah versi sederhana ( inti ) dari jawaban Mick Cullen - sebagian untuk membuktikan bahwa tidak perlu terlalu rumit untuk mengimplementasikannya; sebagian untuk memberikan referensi cepat bagi siapa saja yang tidak tertarik membaca halaman dan halaman kode.


Anda harus membuat aplikasi Anda menggunakan connect-busboy :

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

Ini tidak akan melakukan apa pun sampai Anda memicunya. Dalam panggilan yang menangani pengunggahan, lakukan hal berikut:

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

Mari kita uraikan ini:

  • Anda memeriksa apakah req.busboysudah diatur (middleware dimuat dengan benar)
  • Anda menyiapkan "file"pendengarreq.busboy
  • Anda menyalurkan konten reqkereq.busboy

Di dalam file listener ada beberapa hal yang menarik, tetapi yang terpenting adalah fileStream: ini adalah Readable , yang kemudian dapat ditulis ke file, seperti biasanya.

Kesalahan: Anda harus menangani Readable ini, atau express tidak akan pernah menanggapi permintaan tersebut , lihat busboy API ( bagian file ).

Niels Abildgaard
sumber
21

Saya menemukan ini, sederhana dan efisien:

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

express-fileupload

Yago ML
sumber
Seseorang yang mencari solusi terbaru dengan paket NPM terbaru harus melihat di sini. express-fileupload membuatnya sangat mudah.
jaredbaszler
Jawaban ini adalah contoh yang diberikan di Github, namun melihat ke dalam file repositori, Anda melihat bahwa baris sampleFile.mv...tersebut tertulis uploadPath = __dirname + '/uploads/' + sampleFile.name;- Saya menemukan bahwa sedikit klarifikasi tambahan bermanfaat. Tautan
BrettJ
4

Saya perlu memandu dengan sedikit lebih detail daripada jawaban lain yang diberikan (misalnya bagaimana cara menulis file ke lokasi yang saya putuskan saat runtime?). Semoga ini bisa membantu orang lain:  

dapatkan koneksi-busboy:

npm install connect-busboy --save

Di server.js Anda, tambahkan baris ini

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

Ini tampaknya menghilangkan penanganan kesalahan ... akan mengeditnya jika saya menemukannya.

Edward Newell
sumber
1

Multer adalah middleware node.js untuk menangani multipart / form-data, yang terutama digunakan untuk mengupload file. Itu tertulis di atas busboy untuk efisiensi maksimum.

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('/')

    });
vipinlalrv
sumber
Multer adalah middleware node.js untuk menangani multipart / form-data, yang terutama digunakan untuk mengupload file. Itu tertulis di atas busboy untuk efisiensi maksimum.
vipinlalrv
untuk pemahaman yang lebih baik saya telah mengedit jawaban Anda dengan bagian komentar Anda, saya harap Anda tidak keberatan: P
Pardeep Jain
1

Berikut cara yang lebih mudah yang berhasil untuk saya:

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


});
hamzan
sumber
oh wow itu implementasi yang menarik. Apakah ini berfungsi dengan baik untuk format file yang berbeda?
Merunas Grincalaitis
0

Secara pribadi multer tidak bekerja untuk saya setelah berminggu-minggu mencoba untuk mendapatkan file upload ini dengan benar. Kemudian saya beralih ke tangguh dan setelah beberapa hari saya membuatnya bekerja dengan sempurna tanpa kesalahan, banyak file, express dan react.js meskipun react adalah opsional. Berikut panduannya: https://www.youtube.com/watch?v=jtCfvuMRsxE&t=122s

Merunas Grincalaitis
sumber
0

Jika Anda menggunakan Node.js Express dan Typecript di sini adalah contoh yang berfungsi, ini juga berfungsi dengan javascript, cukup ubah let to var dan impor ke include dll ...

impor pertama yang berikut ini pastikan Anda menginstal tangguh dengan menjalankan perintah berikut:

npm install formidable

daripada mengimpor yang berikut ini:

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

lalu fungsinya seperti di bawah ini:

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