平均堆栈文件上传
Posted
技术标签:
【中文标题】平均堆栈文件上传【英文标题】:MEAN Stack File uploads 【发布时间】:2014-05-21 09:57:16 【问题描述】:我最近开始使用 MEAN Stack 进行编程,目前正在实施某种社交网络。一直在使用 MEAN.io 框架来做到这一点。 我现在的主要问题是让文件上传工作,因为我想要做的是将文件从表单接收到 AngularJS 控制器并将它与更多信息一起传递给 ExpressJS,这样我最终可以将所有内容发送到 MongoDB。 (我正在构建一个注册新用户表单)。
我不想将文件本身存储在数据库中,但我想存储指向它的链接。
我用不同的搜索查询在谷歌上搜索了几十个页面,但我找不到任何我能理解或工作的东西。一直在寻找几个小时没有结果。这就是我来这里的原因。
谁能帮我解决这个问题?
谢谢:)
编辑:也许一些代码会有助于理解。
我用作基础的默认 MEAN.io 用户 Angular 控制器具有:
$scope.register = function()
$scope.usernameError = null;
$scope.registerError = null;
$http.post('/register',
email: $scope.user.email,
password: $scope.user.password,
confirmPassword: $scope.user.confirmPassword,
username: $scope.user.username,
name: $scope.user.fullname
)//... has a bit more code but I cut it because the post is the main thing here.
;
我想做的是: 从表单接收文件到该控制器,并将其与电子邮件、密码、姓名等一起传递,并且能够在位于服务器端的 expressjs 上使用 json。 '/register' 是一个 nodejs 路由,因此是一个服务器控制器,它创建用户(使用用户模式)并将其发送到 MongoDB。
【问题讨论】:
平均上传已过时,现在称为“上传”。它在 - git.mean.io/orit/upload 中进行管理,但即便如此,现在几个月也没有更新...... 【参考方案1】:我最近做了这样的事情。我用angular-file-upload。您还需要 node-multiparty 为您的端点解析表单数据。然后您可以使用s3 将文件上传到s3。
这是我的一些[编辑]代码。
角度模板
<button>
Upload <input type="file" ng-file-select="onFileSelect($files)">
</button>
角度控制器
$scope.onFileSelect = function(image)
$scope.uploadInProgress = true;
$scope.uploadProgress = 0;
if (angular.isArray(image))
image = image[0];
$scope.upload = $upload.upload(
url: '/api/v1/upload/image',
method: 'POST',
data:
type: 'profile'
,
file: image
).progress(function(event)
$scope.uploadProgress = Math.floor(event.loaded / event.total);
$scope.$apply();
).success(function(data, status, headers, config)
AlertService.success('Photo uploaded!');
).error(function(err)
$scope.uploadInProgress = false;
AlertService.error('Error uploading file: ' + err.message || err);
);
;
路线
var uuid = require('uuid'); // https://github.com/defunctzombie/node-uuid
var multiparty = require('multiparty'); // https://github.com/andrewrk/node-multiparty
var s3 = require('s3'); // https://github.com/andrewrk/node-s3-client
var s3Client = s3.createClient(
key: '<your_key>',
secret: '<your_secret>',
bucket: '<your_bucket>'
);
module.exports = function(app)
app.post('/api/v1/upload/image', function(req, res)
var form = new multiparty.Form();
form.parse(req, function(err, fields, files)
var file = files.file[0];
var contentType = file.headers['content-type'];
var extension = file.path.substring(file.path.lastIndexOf('.'));
var destPath = '/' + user.id + '/profile' + '/' + uuid.v4() + extension;
var headers =
'x-amz-acl': 'public-read',
'Content-Length': file.size,
'Content-Type': contentType
;
var uploader = s3Client.upload(file.path, destPath, headers);
uploader.on('error', function(err)
//TODO handle this
);
uploader.on('end', function(url)
//TODO do something with the url
console.log('file opened:', url);
);
);
);
我从我的代码中更改了它,所以它可能无法直接使用,但希望它会有所帮助!
【讨论】:
您好,感谢您的回答!我最终设法使它工作!现在只有一个问题,就是在我提交表单之前上传了图像,但我认为我可以按预期进行工作。我也使用了angular-file-upload
,但是(愚蠢的我)没有检查 Chrome 的控制台是否有错误,我错过了一些双亲,它不起作用(当然!)。但我设法使它工作!不过谢谢你的回答!
@Cacos,我很高兴你成功了。请接受答案,以便紫色从 Google 中查找此内容可以更轻松地找到答案。
另外,作为提示。开发时您可能应该始终打开控制台......没有它很难开发。正如你所发现的...... :-)
完成了,是的,现在我一直在使用始终打开的控制台!新秀失误发生:P
我已尝试按照您的建议和其他类似教程进行操作,但我不断收到错误消息。 'Var file.files[0]' 使我的应用程序崩溃,并给出消息'无法读取未定义的 0'。你知道我的问题可能是什么吗?【参考方案2】:
最近在 mean.io 上的包列表中添加了一个新包。真是个美女!
简单运行:
$ 意味着安装意味着上传
这会将包安装到节点文件夹中,但您可以访问包中的指令。
http://mean.io/#!/packages/53ccd40e56eac633a3eee335
在您的表单视图中,添加如下内容:
<div class="form-group">
<label class="control-label">Images</label>
<mean-upload file-dest="'/packages/photos/'" upload-file-callback="uploadFileArticleCallback(file)"></mean-upload>
<br>
<ul class="list-group">
<li ng-repeat="image in article.images" class="list-group-item">
image.name
<span class="glyphicon glyphicon-remove-circle pull-right" ng-click="deletePhoto(image)"></span>
</li>
</ul>
</div>
在你的控制器中:
$scope.uploadFileArticleCallback = function(file)
if (file.type.indexOf('image') !== -1)
$scope.article.images.push(
'size': file.size,
'type': file.type,
'name': file.name,
'src': file.src
);
else
$scope.article.files.push(
'size': file.size,
'type': file.type,
'name': file.name,
'src': file.src
);
;
$scope.deletePhoto = function(photo)
var index = $scope.article.images.indexOf(photo);
$scope.article.images.splice(index, 1);
享受吧!
【讨论】:
【参考方案3】:平均上传已过时,现在称为“上传”。它被管理在 - https://git.mean.io/orit/upload
【讨论】:
【参考方案4】:我知道这篇文章已经过时了。我遇到了它,@kentcdodds 有一个我非常喜欢的答案,但是他使用的库现在已经过时了,我无法让它们工作。因此,经过一些研究,我想分享一个更新的类似解决方案。
使用 ng-upload 的 HTML
<form >
<div style="margin-bottom: 15px;">
<button type="file" name="file" id="file" ngf-select="uploadFiles($file, $invalidFiles)" accept="image/*" ngf-max- ngf-max-size="1MB">Select File</button>
</div>
</form>
包括 ng-upload 模块
下载它,引用文件并包含模块
var app = angular.module('app', ['ngFileUpload']);
这将使您能够访问Upload
服务。
控制器代码
$scope.uploadFiles = function(file, errFiles)
$scope.f = file;
$scope.errFile = errFiles && errFiles[0];
if (file)
file.upload = Upload.upload(
url: 'you-api-endpoint',
data: file: file
);
//put promise and event watchers here if wanted
;
NODE api 代码
下面的所有代码都在一个单独的 route
文件中,即我的主 server.js 文件中的 required
。
require('./app/app-routes.js')(app, _);
var fs = require('fs');
var uuid = require('uuid');
var s3 = require('s3fs'); // https://github.com/RiptideElements/s3fs
var s3Impl = new s3('bucketname',
accessKeyId: '<your access key id>',
secretAccessKey: '< your secret access key >'
);
var multiparty = require('connect-multiparty');
var multipartyMiddleware = multiparty();
module.exports = function(app, _)
app.use(multipartyMiddleware);
app.post('/your-api-endpoint',function(req, res)
var file = req.files.file; // multiparty is what allows the file to to be accessed in the req
var stream = fs.createReadStream(file.path);
var extension = file.path.substring(file.path.lastIndexOf('.'));
var destPath = '/' + req.user._id + '/avatar/' + uuid.v4() + extension;
var base = 'https://you-bucket-url';
return s3Impl.writeFile(destPath, stream, ContentType: file.type).then(function(one)
fs.unlink(file.path);
res.send(base + destPath);
);
);
我所做的只是为用户上传一个独特的头像。希望这会有所帮助!
【讨论】:
以上是关于平均堆栈文件上传的主要内容,如果未能解决你的问题,请参考以下文章
Vue Apollo 上传文件崩溃节点最大调用堆栈大小超过 _openReadFs