无法使用http-server wiki示例

我做了一个使用AngularJs的Web应用程序,用户可以使用ng-file-upload将.txtfile upload到服务器。

现在我想要一个简单的Node.js服务器来testing上传部分,并观察页面中的进度条和错误消息的行为, 对Node.js和整个后端的工作方式知之甚less,我尝试使用由ng-file-upload提供的非常wiki的 Node.js服务器。

我试图做一些改变,把我带到这个app.js文件:

 var http = require('http') , util = require('util') , multiparty = require('multiparty') , PORT = process.env.PORT || 27372 var server = http.createServer(function(req, res) { if (req.url === '/') { res.writeHead(200, {'content-type': 'text/html'}); res.end( '<form action="/upload" enctype="multipart/form-data" method="post">'+ '<input type="text" name="title"><br>'+ '<input type="file" name="upload" multiple="multiple"><br>'+ '<input type="submit" value="Upload">'+ '</form>' ); } else if (req.url === '/upload') { var form = new multiparty.Form(); form.parse(req, function(err, fields, files) { if (err) { res.writeHead(400, {'content-type': 'text/plain'}); res.end("invalid request: " + err.message); return; } res.writeHead(200, {'content-type': 'text/plain'}); res.write('received fields:\n\n '+util.inspect(fields)); res.write('\n\n'); res.end('received files:\n\n '+util.inspect(files)); }); } else { res.writeHead(404, {'content-type': 'text/plain'}); res.end('404'); } }); server.listen(PORT, function() { console.info('listening on http://127.0.0.1:'+PORT+'/'); }); 

UserController.js是这样简单

 UserController = function() {}; UserController.prototype.uploadFile = function(req, res) { // We are able to access req.files.file thanks to // the multiparty middleware var file = req.files.file; console.log(file.name); console.log(file.type); } module.exports = new UserController(); 

在AngularJs应用程序的指令控制器中,我使用ng-file-upload 上传服务

 var upload = Upload.upload({ url: 'http://127.0.0.1:27372/upload', method: 'POST', fields: newFields, file: newFile }).progress(function (evt) { $scope.progressPercentage = parseInt(100.0 * evt.loaded / evt.total); }).success(function (data, status, headers, config) { console.log("OK"); }).error(function(data, status, headers, config) { console.log("KO"); }); 

最后,我开始这样的服务器

 node app.js 

一切都很美好

 listening on http://127.0.0.1:27372 

尽pipe如此,当我启动AngularJsnetworking应用程序,并尝试上传文件,我得到以下错误

 OPTIONS http://127.0.0.1:27372/upload 400 (Bad Request) angular.js:10514 XMLHttpRequest cannot load http://127.0.0.1:27372/upload. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 400. (index):1 

经过一些Googlesearch之后,我发现许多gist用于允许像这样的 CORS请求,但我的Node.js知识是如此之差,我甚至不知道我应该把这些代码行放在哪里。

此外,我试图得到一个console.log(err)内的app.js form.parse部分本身,并得到这个打印在terminal上:

 DEBUG SERVER: err = { [Error: missing content-type header] status: 415, statusCode: 415 } 

我错过了什么,我能做些什么来获得这个简单的Node.js服务器的工作?


编辑29/07/2015

我select了@Can Guney Aksakallibuild议的第一个选项,因为这是我唯一可以做的,但即使现在代码看起来像这样:

 var server = http.createServer(function(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); if (req.url === '/') { res.writeHead(200, {'Content-type': 'text/html'}); // and the code stays the same 

这个解决scheme不起作用。 我一直在Chrome控制台和从中调用node app.js的terminal中收到相同的错误消息,正如我在最初的问题的最后一部分中所写的那样。

您正在http://localhost:9000上提供html文件,在http://localhost:27372上提供NodeJS应用程序; 因此你有CORS问题。 (虽然这个问题与angularjs没有关系)。 您必须为NodeJS启用CORS或在同一个域中提供您的所有应用程序。

可能的解决scheme:

1-在NodeJS服务器中启用CORS

您可以在服务器端启用CORS,方法是在响应头中指定允许的来源。 这些行将启用来自所有域的您的应用程序的请求。 (将此添加到函数定义的开头。)

 var server = http.createServer(function(req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); // the rest of the method ... } 

为所有域启用CORS并不总是一个好的决定,请检查这一点 。

2-从NodeJS应用程序提供您的HTML文件

在这里添加以下内容,您将从NodeJS服务器提供您的html文件。 (您不需要再使用其他服务器。)

 var serveStatic = require('serve-static'); var finalhandler = require('finalhandler'); //... var serve = serveStatic('./path/to/your/static/folder'); var server = http.createServer(function(req, res) { //... var done = finalhandler(req, res); serve(req, res, done); }); 

我也build议您使用ExpressJS来获得更丰富的服务器function,而不是使用vanilla node.js http服务器。

3-提供从您的html文件服务器到nodejs应用程序的代理连接

我不知道你用作静态html文件的服务器,但是你的静态服务器和NodeJS应用服务器之间可以有代理。


编辑1

这里是选项2- Serving your html files from NodeJS application一个基本实现2- Serving your html files from NodeJS application

在这个例子中,我使用ExpressJS。 客户端的静态文件在公共文件夹中提供,对于/api/upload url的post请求将会上传文件。 这里是服务器代码app.js

 var express = require('express'), path = require('path'), multiparty = require('connect-multiparty'), multipartyMiddleware = multiparty(), PORT = process.env.PORT || 27372; var app = express(); app.use(express.static(path.join(__dirname, 'public'))); app.post('/api/upload', multipartyMiddleware, function(req, res) { var file = req.files.file; console.log(file.name); console.log(file.type); console.log(file.path); }); var server = app.listen(PORT, function() { var host = server.address().address; var port = server.address().port; console.log('the App listening at http://%s:%s', host, port); }); 

现在公用文件夹被提供给根url。 这里是客户端文件public/index.html

 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>Upload example</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> </head> <body> <div class="container"> <div> <h1>Upload example</h1> <hr /> <div ng-app="fileUpload" ng-controller="MyCtrl"> <button type="button" class="btn btn-default" ngf-select ng-model="file">Upload using model $watch</button> </div> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script> <script src="http://rawgit.com/danialfarid/ng-file-upload/master/dist/ng-file-upload.min.js"></script> <script> var app = angular.module('fileUpload', ['ngFileUpload']); app.controller('MyCtrl', ['$scope', 'Upload', function($scope, Upload) { $scope.$watch('file', function() { var file = $scope.file; if (!file) { return; } Upload.upload({ url: 'api/upload', file: file }).progress(function(evt) { var progressPercentage = parseInt(100.0 * evt.loaded / evt.total); console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name); }).success(function(data, status, headers, config) { console.log('file ' + config.file.name + 'uploaded. Response: ' + data); }).error(function(data, status, headers, config) { console.log('error status: ' + status); }) });; }]); </script> </body> </html> 

现在,您可以运行node app并使用浏览器在localhost:27372进行尝试。

(这里是要点版本: https : //gist.github.com/aksakalli/1a56072f066d65248885 )


编辑2

以下是选项1- Enabling CORS in NodeJS server的基本实现。 我正在使用Cors包来处理标题configuration,现在app.js代码将如下所示:

 var express = require('express'), multiparty = require('connect-multiparty'), cors = require('cors'), multipartyMiddleware = multiparty(), app = express(), PORT = process.env.PORT || 27372; app.use(cors()); app.post('/api/upload', multipartyMiddleware, function(req, res) { var file = req.files.file; console.log(file.name); console.log(file.type); console.log(file.path); }); var server = app.listen(PORT, function() { var host = server.address().address; var port = server.address().port; console.log('the App listening at http://%s:%s', host, port); }); 

对于第一个错误:

 OPTIONS http://127.0.0.1:27372/upload 400 (Bad Request) angular.js:10514 

您正在使用的ng-file-upload上传服务会在请求前删除Content-Type标头,如此处所示。 但是来自多方的分析方法似乎需要它。 如果你是从wiki中给出的例子开始工作,那么我build议你也使用express和multiparty作为中间件,就像在这个例子中说的那样。

你的app.js看起来像这样:

 var express = require('express'), // Requires multiparty multiparty = require('connect-multiparty'), multipartyMiddleware = multiparty(); var app = express(); app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); next(); }); // Example endpoint app.post('/upload', multipartyMiddleware, function(req, res) { // We are able to access req.files.file thanks to // the multiparty middleware var file = req.files.file; console.log(file.type); console.log(file.name); }); app.listen(27372); 

对于第二个错误:这是一个CORS问题,如上所述。 build议的app.js应该允许CORS,因为有以下几行:

 app.all('*', function(req, res, next) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "X-Requested-With"); next(); });