Интеграция файлового загрузчика для angularjs
Существует ли хороший файл-загрузчик с хорошей интеграцией (директива) для AngularJS?
Я ищу что-то, что легко стильно и поддерживает перетаскивание HTML5 и т.д.
Кто-то, вероятно, скажет, что его простой в использовании существующий загрузчик и интеграция его в AngularJS - к тому, что я скажу: если его легко, то кто-то должен был это сделать уже.
Ответы
Ответ 1
Я действительно закатил свой собственный загрузчик один раз... но только потому, что мне не нравились уже сделанные JQuery. К сожалению, это проприетарное, и я не могу опубликовать его в Интернете... но... Я могу показать вам, как использовать практически любой плагин JQuery из Angular:
Кто-то, вероятно, скажет, что его простой в использовании существующий загрузчик и интеграция его в AngularJS - к тому, что я скажу: если его легко, то кто-то должен был сделать это уже.
Предположим, что у меня есть плагин jQuery, который работает, выбирая div и вызывающий pluginUploadCall()
на нем...
app.directive('myJqueryPluginUploader', function() {
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
// elem is a jQuery lite object
// or a jQuery object if jQuery is present.
// so call whatever plugins you have.
elem.pluginUploadCall();
}
};
});
И вот как он будет использоваться.
<div my-jquery-plugin-uploader></div>
Angular действительно хорошо интегрируется с jQuery, поэтому любые плагины, которые работают в jQuery, должны работать довольно легко в Angular. Единственная хитрость возникает, когда вы хотите сохранить Injection Dependency вживую, чтобы вы могли поддерживать приложение Angular. JQuery не очень хорош в DI, поэтому вам, возможно, придется перепрыгнуть через некоторые обручи.
Если бы вы хотели перевернуть свои собственные, я могу сказать, что я сделал что-то вроде этого:
app.directive('customUploader', function(){
return {
restrict: 'E',
scope: {},
template: '<div class="custom-uploader-container">Drop Files Here<input type="file" class="custom-uploader-input"/><button ng-click="upload()" ng-disabled="notReady">Upload</button></div>',
controller: function($scope, $customUploaderService) {
$scope.notReady = true;
$scope.upload = function() {
//scope.files is set in the linking function below.
$customUploaderService.beginUpload($scope.files);
};
$customUploaderService.onUploadProgress = function(progress) {
//do something here.
};
$customUploaderService.onComplete = function(result) {
// do something here.
};
},
link: function(scope, elem, attr, ctrl) {
fileInput = elem.find('input[type="file"]');
fileInput.bind('change', function(e) {
scope.notReady = e.target.files.length > 0;
scope.files = [];
for(var i = 0; i < e.target.files.length; i++) {
//set files in the scope
var file = e.target.files[i];
scope.files.push({ name: file.name, type: file.type, size: file.size });
}
});
}
});
Где $customUploaderService
будет создаваться пользовательский сервис с Module.factory()
, который использует $http
для публикации файлов и проверки прогресса на сервере.
Я знаю это расплывчатое, и мне жаль, что все, что я могу предоставить, но надеюсь, что это поможет.
EDIT: Загрузка файла перетаскивания - это немного трюк CSS, BTW... для Chrome и FF, то, что вы делаете, помещается в содержащий div... затем сделайте что-то вроде этого:
<div class="uploadContainer">Drop Files Here<input type="file"/></div>
div.uploadContainer {
position: relative;
width: 600px;
height: 100px;
}
div.uploadContainer input[type=file] {
visibility: hidden;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
... теперь все, что вы бросаете на этом div, действительно будет удалено при загрузке файла, и вы можете заставить div выглядеть так, как вам хочется.
Ответ 2
Вы можете попробовать AngularJS.ngUpload.
Это решение без HTML5, которое использует невидимый iFrame для загрузки файлов. Поскольку он не полагается на HTML5, он работает в браузере!
Пример кода:
<form action='/server/upload/handler' ng-upload="callbackFunction">
<!-- other form inputs goes here -->
<input type="file" name="anyEasyName" />
<input type="submit" class="upload-submit" value="Submit" />
</form>
<div>{{uploadReport}}</div>
Любой элемент html, который поддерживает событие click, может быть использован для отправки формы, помеченной директивой ngUpload, только чтобы такие элементы были отмечены классом upload-submit css (в случае с вход [type = submit] выше.
В приведенном ниже примере используется стилизованный div для отправки формы.
<form action='/server/upload/handler' ng-upload="callbackFunction">
<!-- other form inputs goes here -->
<input type="file" name="anyEasyName" />
<div style="cursor: pointer; padding: 5px" class="upload-submit">Submit</div>
</form>
<div>{{uploadReport}}</div>
Вы можете заставить ваш/сервер/загрузку/обработчик спрятать действительный URL-адрес, чтобы {{uploadReport}} мог использоваться для установки src в <img> тег, например:
<img ng-src={{uploadReport}} />
и сразу увидите загруженное изображение!
ngController для приведенных выше примеров:
var UploadCtrl = function ($scope) {
$scope.callbackFunction = function(contentOfInvisibleFrame) {
$scope.uploadReport = contentOfInvisibleFrame;
}
}
Директива ngUpload может быть зарегистрирована в вашем прикладном модуле AngularJS, а именно:
var mainApp = angular.module('MainApp', ["ngUpload", ...]);
и добавлен в ваш документ как:
<html ng-app="MainApp">
</html>
AngularJS.ngUpload работает в контексте ngController; и у вас может быть как можно больше пользователей в одном ngController. Например:
<form action='/server/upload/handler' ng-upload="callbackFunction1">
<!-- other form inputs goes here -->
<input type="file" name="anyEasyName" />
<input type="submit" class="upload-submit" value="Submit" />
</form>
Server response: {{uploadReport1}}
<form action='/server/upload/handler' ng-upload="callbackFunction2">
<!-- other form inputs goes here -->
<input type="file" name="anotherEasyName" />
<input type="submit" class="upload-submit" value="Submit" />
</form>
Server response: {{uploadReport2}}
для обслуживания:
var UploadCtrl = function ($scope) {
$scope.callbackFunction1 = function(contentOfInvisibleFrame) {
$scope.uploadReport1 = contentOfInvisibleFrame;
}
$scope.callbackFunction2 = function(contentOfInvisibleFrame) {
$scope.uploadReport2 = contentOfInvisibleFrame;
}
}
Демоверсию обработчика загрузки NodeJS этой директивы можно найти на http://ng-upload.eu01.aws.af.cm.
Примеры кода ASP.Net MVC и NodeJS можно найти на веб-сайте проекта по адресу github.com/twilson63/ngUpload/tree/master/examples
Надеюсь, что это поможет.
Ответ 3
Я собрал простую/легкую директиву angular с polyfill для браузеров, не поддерживающих HTML5 FormData здесь:
https://github.com/danialfarid/ng-file-upload
Вы можете отправить другой объект модели вместе с файлом на сервер.
Вот демонстрационная страница:
http://angular-file-upload.appspot.com/
<script src="angular.min.js"></script>
<script src="ng-file-upload.js"></script>
<div ng-controller="MyCtrl">
<input type="text" ng-model="myModelObj">
<input type="file" ngf-select ng-model="files" >
</div>
контроллер:
Upload.upload({
url: 'my/upload/url',
data: {myObj: $scope.myModelObj},
file: $scope.files
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
});
Ответ 4
Если вы хотите обрабатывать несколько файлов, попробуйте это
jQuery Загрузка файла Angularjs wrap от оригинального автора (blueimp)
Я думаю, что это самый мощный загрузчик.
Ответ 5
Недавно я написал директиву, поддерживающую несколько загрузок файлов.
Пример использования:
<lvl-file-upload
auto-upload='false'
choose-file-button-text='Choose files'
upload-file-button-text='Upload files'
upload-url='http://localhost:3000/files'
max-files='10'
max-file-size-mb='5'
get-additional-data='getData(files)'
on-done='done(files, data)'
on-progress='progress(percentDone)'
on-error='error(files, type, msg)'/>
Вы можете найти код на github, а документацию на my блог