无法使用 http-server wiki 示例
Posted
技术标签:
【中文标题】无法使用 http-server wiki 示例【英文标题】:Unable to use http-server wiki example 【发布时间】:2015-10-14 20:35:31 【问题描述】:我使用 AngularJs 制作了一个网络应用程序,用户可以使用 ng-file-upload 将 .txt
文件上传到服务器。
现在我想要一个简单的 Node.js 服务器来测试上传部分并观察页面中的进度条和错误消息的行为,但是对 Node.js 和整个后端工作正常,我尝试使用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
话虽如此,当我启动 AngularJs 网络应用并尝试上传文件时,我收到以下错误
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
经过一番谷歌搜索后,我发现许多用于允许 CORS 请求的要点,如 this one,但我的 Node.js 知识太差了,我什至不知道应该将这些代码行放在哪里。
此外,我尝试在 app.js
form.parse
部分本身中获取 console.log(err)
并将其打印在终端上:
DEBUG SERVER: err =
[Error: missing content-type header] status: 415, statusCode: 415
我缺少什么以及我可以做些什么来获得这个简单的 Node.js 服务器 工作吗?
编辑 29/07/2015
我选择遵循 @Can Guney Aksakalli 建议的第一个选项,因为这是我唯一能做的,但即使现在代码看起来像这样:
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
这个解决方案不起作用;正如我在最初问题的最后一部分中所写的那样,我在 Chrome 控制台和我调用 node app.js
的终端中不断收到相同的错误消息。
【问题讨论】:
我添加了示例代码来解决 CORS 问题。 【参考方案1】:对于第一个错误:
OPTIONS http://127.0.0.1:27372/upload 400 (Bad Request) angular.js:10514
您正在使用的 ng-file-upload Upload 服务会在请求之前删除 Content-Type 标头,如 here 所示。 但是多方的解析方法似乎需要它。 如果您正在使用 wiki 中的给定示例,我建议您也使用 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 问题。由于以下几行,建议的 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();
);
【讨论】:
对于你的第一个答案:伙计,我在我的问题中说我不太了解 Node,所以我不知道你说我必须“使用 express 和 multiparty 作为中间件是什么意思";对于第二个答案,每次更改代码中的某些内容时,我都会重新启动 Node 服务器 您提供的wiki link 在第一句话中指出,此示例使用 express 和 connect-multiparty(即连接中间件包)。它还提供了到express webpage 和connect-multiparty 的链接。我假设您可能已经阅读了这些链接。此外,您永远不会在代码中的任何位置包含 UserController.js。 实际上我认为该 wiki 上的代码会更易于使用,因为我只需要简单的服务器来测试我的前端。此外,@Can Guney 似乎也没有在他提供的解决方案中包含 UserController.js,这让我有点困惑 我编辑了我的答案。它包含您期望从 wiki 获得的即用型示例。 UserController.js 被省略,因为它实际上对于示例来说是非常不必要的。相反,app.js 中提供了一个回调函数。 @Gargarozmodule.exports
将给定的定义导出到另一个 nodejs 文件。它基本上是给app.post
一个函数参数来处理请求。我们的示例将文字函数作为参数。我们也可以将处理程序作为参考传递...【参考方案2】:
您在http://localhost:9000
上提供html 文件,在http://localhost:27372
上提供NodeJS 应用程序;因此你有 CORS 问题。 (虽然这个问题与 angularjs 无关)。您必须为 NodeJS 启用 CORS 或在同一域中提供所有应用程序。
可能的解决方案:
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 并不总是一个好的决定,另请查看 this。
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);
);
我还建议您使用 ExpressJS 来获得更丰富的服务器功能,而不是 vanilla node.js http 服务器。
3- 提供从您的 html 文件服务器到 nodejs 应用程序的代理连接
我不知道您将什么用作静态 html 文件的服务器,但可以在您的静态服务器和 NodeJS 应用程序服务器之间建立代理。
编辑 1
这是选项2- Serving your html files from NodeJS application
的基本实现。
在这个例子中,我使用了 ExpressJS。客户端静态文件在公共文件夹中提供,对于/api/upload
url 的发布请求将上传文件。这里是服务器代码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);
);
现在public
文件夹提供给根 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 包来处理标头配置,现在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);
);
【讨论】:
您好,感谢您的回答;我编辑了我的答案,我希望你检查一下。 @Gargaroz 我为您编写了一个示例应用程序。我试过了,应该可以的。 感谢您在此答案中付出的努力,明天我会检查您的解决方案是否有效以上是关于无法使用 http-server wiki 示例的主要内容,如果未能解决你的问题,请参考以下文章
Facebook Flux todomvc 教程 - 由于 package.json 文件,无法启动简单的节点 http-server
Ubuntu:端口 80 上的 Http-server 启动,但无法从浏览器访问?