Node/Express 文件上传

我使用的是节点 v0.10.26和 Expressv4.2.0,对于 node 我是相当新的。在过去的三个多小时里,我一直在我的桌子上绞尽脑汁,试图让一个文件上传表单与节点一起工作。此时,我只是尝试让 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;

这是我的应用程序

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})应该有所帮助,但我甚至不能启动我的服务器,如果我添加这些行。

288467 次浏览

特快专递发行日期:

中间件的大部分从 Express4中删除。 看看 http://www.github.com/senchalabs/connect#middleware 对于多部分中间件,如餐厅杂工,餐厅杂工-连接,强大,流程,分开是必要的。

This example works using 餐厅服务员 middleware. 创建/img 和/public 文件夹。
使用文件夹结构:

Server.js

“上传到哪里”

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

下面是 Mick Cullen 的 回答的简化版本(大意)——部分是为了证明实现它不需要非常复杂; 部分是为了给那些对阅读代码页不感兴趣的人提供一个快速参考。


你必须让你的应用程序使用 餐厅服务员:

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(中间件已正确加载)
  • You set up a "file" listener on req.busboy
  • req的内容通过管道传送到 req.busboy

在文件侦听器内部有一些有趣的东西,但真正重要的是 fileStream: 这是一个 可读,然后可以像通常那样写到一个文件中。

陷阱: You must handle this Readable, or express will never respond to the request,参见 餐厅服务员 API(文件部分)。

另一种选择是使用 Multer,它在引擎盖下使用餐馆小弟,但是设置起来更简单。

var multer = require('multer');

Use multer and set the destination for the upload:

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

Create a form in your view, enctype='multipart/form-data is required for multer to work:

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

这方面的完整教程可以找到 给你

我需要了解比其他答案更多的细节(例如,我如何将文件写到我在运行时决定的位置?).希望这对其他人有所帮助:

服务生:

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

这似乎省略了错误处理,虽然... 将编辑它,如果我找到它。

Multer 是一个 node.js 中间件,用于处理 multipart/form-data,主要用于上传文件。为了最大限度地提高效率,它被写在服务生的顶部。

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


});

我发现这个简单而有效:

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 文件上传

Here is an easier way that worked for me:

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




});

我个人认为 Multer 不适合我,几个星期后,试图得到这个文件上传事情的权利。然后我切换到强大的,几天后,我得到了它的工作完美没有任何错误,多个文件,表达和 react.js,即使反应是可选的。这是指南: https://www.youtube.com/watch?v=jtCfvuMRsxE&t=122s

如果您正在使用 Node.js Express,这里的 Typecript 是一个工作示例,这也适用于 javascript,只需将 let 更改为 var,将 import 更改为 include 等。.

首先导入以下命令,确保通过运行以下命令安装强大的程序:

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();
});
});
}
const http          = require('http');
const fs            = require('fs');


// https://www.npmjs.com/package/formidable
const formidable    = require('formidable');


// https://stackoverflow.com/questions/31317007/get-full-file-path-in-node-js
const path          = require('path');


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


let oldpath = req.files.fileUploaded.path;


// https://stackoverflow.com/questions/31317007/get-full-file-path-in-node-js
let newpath = path.resolve( `./${req.files.fileUploaded.name}` );


// copy
// https://stackoverflow.com/questions/43206198/what-does-the-exdev-cross-device-link-not-permitted-error-mean
fs.copyFile( oldpath, newpath, (err) => {


if (err) throw err;


// delete
fs.unlink( oldpath, (err) => {


if (err) throw err;


console.log('Success uploaded")
} );


} );


});

在香草节,我想到了一个办法。只是个快速上传服务器。不是那种花哨的快车。可能不是提问者想要的。

const fs = require('fs'),
http = require('http'),
port = process.env.PORT || 9000,
host = process.env.HOST || '127.0.0.1';
//tested on node=v10.19.0, export HOST="192.168.0.103"
http.createServer(function(req, res) {


// Check if form is submitted and save its content
if (req.method == "POST") try {
store_file(req)


// This is here incase any errors occur
} catch (err) {
res.writeHead(404);
res.end('Server Borked');
return;
}


// respond with a simple html form so they can post more data
res.writeHead(200, {"content-type":"text/html; charset=utf-8"});
res.end(`
<form  method="post" enctype="multipart/form-data">
<input type="file" name="fileUpload">
<input type="submit" value="Upload">
</form>`);
}).listen(port, host, () => console.dir(`Serving at http://${host}:${port}`));


function store_file(req) {
// Generate temporary file name
var temp = 'temp' + Math.floor(Math.random() * 10);


// This opens up the writeable stream to temporary file
var writeStream = fs.createWriteStream(temp);


// This pipes the POST data to the file
req.pipe(writeStream);


// After the temporary file is creates, create real file
writeStream.on('finish', () => {


reader = fs.readFileSync(temp);
filename = reader.slice(reader.indexOf("filename=\"") + "filename=\"".length, reader.indexOf('"\r\nContent-Type'));
hash = reader.slice(0,reader.indexOf('\r\n'));
content = reader.slice(reader.indexOf('\r\n\r\n') + '\r\n\r\n'.length, reader.lastIndexOf(Buffer.from('\r\n') + hash));


// After real file is created, delete temporary file
fs.writeFileSync(filename.toString(), content);
fs.unlinkSync(temp);
});
}