无法使用http-server wiki示例
Unable to use http-server wiki example
我使用AngularJs制作了一个web应用程序,用户可以使用ng-file-upload将.txt
文件上传到服务器。
现在我想要一个简单的Node.js服务器来测试上传部分,并观察页面中的进度条和错误消息如何表现,但是对Node.js和整个后端工作方式的了解非常差,我试图使用ng-file-upload
提供的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 web应用程序并尝试上传文件时,我得到以下错误
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
经过一些谷歌搜索,我发现许多gist过去允许像这样的CORS请求,但我的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
的终端中不断得到相同的错误信息,正如我在最初问题的最后一部分所写的。
您在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并不总是一个好决定,请也检查一下。
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来提供更丰富的服务器功能,而不是普通的node.js http服务器。
3-提供从html文件服务器到nodejs应用程序的代理连接
我不知道你是用什么作为静态html文件的服务器,但有可能在你的静态服务器和NodeJS应用服务器之间有一个代理。
编辑1
下面是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);
});
现在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);
});
OPTIONS http://127.0.0.1:27372/upload 400 (Bad Request) angular.js:10514
您正在使用的ng-file-upload上传服务会在请求之前删除Content-Type报头,如图所示。但是来自多方的解析方法似乎需要它。如果您正在使用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();
});
- PHP AJAX图片上传示例不上传
- API密钥使用和检查示例
- 三星智能电视应用程序;Brightcove示例应用程序远程控制问题
- 骨干模型默认值-todos.js示例中不必要的代码
- d3js文本传输-示例代码不起作用
- Eloquent JavaScript递归示例如何终止为返回1,但仍然输出指数值
- JQuery示例不起作用-“;对象没有't支持属性或方法'按钮'&”;
- 来自MDN的循环示例的JavaScript不起作用
- 如何使相机跟随地形's在此示例中的高度:http://threejs.org/examples/#webgl_t
- 谷歌应用程序脚本示例-如何更改单选按钮的列表框相关值
- AngularJS控制器不工作,为什么?(简单的控制器示例)
- d3绘制动画折线图的基本示例
- JavaScript原型示例
- 如何将此示例函数调整为Backbone
- 无法在我的示例plunker中使用继承/隔离的范围概念
- onbeforeunload事件在我的代码中没有触发,但其他示例可以工作
- 承诺-如何正确地将错误附加到此示例
- JSON:loop Invoice Items:如果InvoiceNo未退出则添加,如果退出则更新值,示例包括在内
- 如何在javascript中创建一个空的2d数组?下面是我想要创建的一个示例
- 无法使用http-server wiki示例