Загрузка файлов MEAN Stack
Недавно я начал программирование с помощью MEAN Stack, и в настоящее время я реализую какую-то социальную сеть. Для этого используется среда MEAN.io.
Моя главная проблема прямо сейчас заключается в том, чтобы загрузить файл на работу, потому что я хочу получить файл из формы в контроллер AngularJS и передать его вместе с дополнительной информацией в ExpressJS, чтобы я мог, наконец, отправить все в MongoDB. (Я создаю регистрационную новую пользовательскую форму).
Я не хочу хранить сам файл в базе данных, но хочу сохранить ссылку на него.
Я искал десятки страниц в Google с разными поисковыми запросами, но я не мог найти ничего, что мог бы понять или сработать. Был поиск часов без каких-либо результатов. Вот почему я пришел сюда.
Может ли кто-нибудь помочь мне с этим?
Спасибо:)
EDIT: Может быть, немного кода поможет понять.
По умолчанию контроллер MEAN.io Users 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.
};
Что я хочу сделать:
Получите файл из формы на этот контроллер и передайте его вместе с электронной почтой, паролем, именем и т.д. И т.д. И сможете использовать json on expressjs, который находится на стороне сервера.
"/Register" - это маршрут nodejs, поэтому серверный контроллер создает пользователя (с пользовательской схемой) и отправляет его в MongoDB.
Ответы
Ответ 1
Недавно я сделал что-то подобное. Я использовал angular-file-upload. Вы также захотите node-multiparty для вашей конечной точки проанализировать данные формы. Затем вы можете использовать s3 для загрузки файла на s3.
Вот некоторые из моих [отредактированных] кодов.
Angular Шаблон
<button>
Upload <input type="file" ng-file-select="onFileSelect($files)">
</button>
Angular Контроллер
$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);
});
});
});
}
Я изменил это из своего кода, поэтому он может не работать из коробки, но, надеюсь, это полезно!
Ответ 2
Недавно новый пакет был добавлен в список пакетов на mean.io. Это красота!
Просто запустите:
$mean install mean-upload
Это устанавливает пакет в папку node, но у вас есть доступ к директивам в ваших пакетах.
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
Средняя загрузка была устарела и теперь называется "upload". Он управляется в https://git.mean.io/orit/upload
Ответ 4
Я знаю, что этот пост старый. Я столкнулся с этим, и у @kentcdodds был ответ, который мне очень понравился, но библиотеки, которые он использовал, теперь устарели, и я не мог заставить их работать. Поэтому после некоторых исследований у меня появилось более новое подобное решение, которое я хочу разделить.
HTML с использованием ng-upload
<form >
<div style="margin-bottom: 15px;">
<button type="file" name="file" id="file" ngf-select="uploadFiles($file, $invalidFiles)" accept="image/*" ngf-max-height="1000" 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
, который required
в моем основном файле server.js.
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);
});
});
Все, что я пытался сделать, это загрузить уникальный аватар для пользователя. Надеюсь, это поможет!