成果图:
main-hugeScreen.html
<div class="hbox hbox-auto-xs hbox-auto-sm" ng-controller="HugeScreenCtrl">
<!--div ng-controller="HugeScreenCtrl">
<div class="col w-lg bg-light b-r bg-auto">
<div class="wrapper-md dker b-b">
<h3 class="m-n font-thin">选择文件</h3>
</div>
<div class="wrapper-md">
<p>多个文件</p>
<input type="file" multiple/>
<p class="m-t-md">单个文件</p>
<input type="file"/>
</div>
</div>
<div>
<input type="file" file-model="myFile" multiple/>
<button ng-click="uploadFile()">upload me</button>
</div>
</div-->
<div class="col w-lg bg-light b-r bg-auto">
<div class="wrapper-md dker b-b">
<h3 class="m-n font-thin">Select files</h3>
</div>
<div class="wrapper-md">
<div ng-show="true" class="m-b-md">
<!-- 3. nv-file-over uploader="link" over-class="className" -->
<div file-dropzone="[image/png, image/jpeg, image/gif]"
files="myFile" over-class='b-danger' data-max-file-size="3" class="b-a b-2x b-dashed wrapper-lg bg-white text-center m-b">
Base drop zone
</div> <!-- Example: nv-file-drop="" uploader="{Object}" options="{Object}" filters="{String}" -->
<div>
<div file-dropzone="[image/png, image/jpeg, image/gif]"
files="myFile" over-class='b-info' data-max-file-size="3" active="redColorActive" class="b-a b-2x b-dashed wrapper-lg lter text-center" >
Another drop zone with its own settings
</div>
</div>
</div> <!-- Example: nv-file-select="" uploader="{Object}" options="{Object}" filters="{String}" -->
<p>Multiple</p>
<input type="file" file-model="myFile" multiple/> <p class="m-t-md">Single</p>
<input type="file" file-model="myFile"/>
</div>
</div>
<div class="col">
<div class="wrapper-md bg-light dk b-b">
<span class="pull-right m-t-xs">Queue length: <b class="badge bg-info">{{myFile.length}}</b></span>
<h3 class="m-n font-thin">Upload queue</h3>
</div>
<div class="wrapper-md">
<table class="table bg-white-only b-a">
<thead>
<tr>
<th width="30%">缩略图</th>
<th width="30%">Name</th>
<th ng-show="true">Size</th>
<th ng-show="true">Progress</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in myFile">
<!--td><img ng-src={{item.stream}}/></td-->
<td><img ng-src={{item.stream}} style="max-width: 200px; max-height: 200px"/></td>
<td><strong>{{ item.file.name }}</strong></td>
<td ng-show="true" nowrap>{{ item.file.size/1024/1024|number:2 }} MB</td>
<td ng-show="true">
<div class="progress progress-sm m-b-none m-t-xs">
<div class="progress-bar bg-info" role="progressbar" ng-style="{ 'width': item.progress + '%' }"></div>
</div>
</td>
<td class="text-center">
<span ng-show="item.isSuccess" class="text-success"><i class="glyphicon glyphicon-ok"></i></span>
<span ng-show="item.isCancel" class="text-warning"><i class="glyphicon glyphicon-ban-circle"></i></span>
<span ng-show="item.isError" class="text-danger"><i class="glyphicon glyphicon-remove"></i></span>
</td>
<td nowrap>
<button type="button" class="btn btn-default btn-xs" ng-click="item.upload(item)" ng-disabled="item.isReady || item.isUploading || item.isSuccess">
Upload
</button>
<button type="button" class="btn btn-default btn-xs" ng-click="removeItem($index)">
Remove
</button>
</td>
</tr>
</tbody>
</table>
<div>
<div>
<p>Queue progress:</p>
<div class="progress bg-light dker" style="">
<div class="progress-bar progress-bar-striped bg-info" role="progressbar" ng-style="{ 'width': allprogress + '%' }"></div>
</div>
</div>
<button type="button" class="btn btn-addon btn-success" ng-click="uploadAllfiles(allprogress)">
<i class="fa fa-arrow-circle-o-up"></i> Upload all
</button>
<button type="button" class="btn btn-addon btn-warning" ng-click="cancelAll()" ng-disabled="!myFile.isUploading">
<i class="fa fa-ban"></i> Cancel all
</button>
<button type="button" class="btn btn-addon btn-danger" ng-click="clearQueue()" ng-disabled="!myFile.length">
<i class="fa fa-trash-o"></i> Remove all
</button>
<p class="text-muted m-t-xl">Note: upload.php file included, files will be uploaded to "src/js/controllers/uploads".</p>
</div>
<div>
<table><thead><tr><th>缩略图</th></tr></thead><tbody>
<tr ng-repeat="item in image track by $index">
<td>
<img ng-src={{item}} />
</td>
</tr>
</tbody></table> <!-- <span class="file-name">{{imageFileName}}</span>-->
</div>
</div>
</div>
</div>
bjt-imageload-service.js
/**
* Created by chaiqiaozhen on 10/6/15.
*/
app.service('fileReader', function ($q) { var fileReader = this;
fileReader.onLoad = function(file, reader,deferred, scope) {
return function () {
scope.$apply(function () {
var ret = {
srcfile: file,
stream: reader.result
};
deferred.resolve(ret);
});
};
}; fileReader.onError = function (reader, deferred, scope) {
return function () {
scope.$apply(function () {
deferred.reject(reader.result);
});
};
}; fileReader.onProgress = function(reader, scope) {
return function (event) {
scope.$broadcast("fileProgress",
{
total: event.total,
loaded: event.loaded
});
};
}; fileReader.getReader = function(file,deferred, scope) {
var reader = new FileReader();
reader.onload = fileReader.onLoad(file, reader,deferred, scope);
reader.onerror = fileReader.onError(reader, deferred, scope);
reader.onprogress = fileReader.onProgress(reader, scope);
return reader;
}; fileReader.readMyAsDataURL = function (file, scope) {
var deferred = $q.defer(); var reader = fileReader.getReader(file, deferred, scope);
reader.readAsDataURL(file); return deferred.promise;
}; });
hugeScreen-service.js
app.directive('fileDropzone', ['$bjtHttpService','fileReader',function($bjtHttpService,fileReader) {
return {
restrict: 'A',
scope: {
files: '=',
overClass: '='
},
link: function(scope, element, attrs) {
var checkSize, isTypeValid, processDragOverOrEnter, validMimeTypes,getDataTransfer,addfile;
var fileList = [];
addfile = function(item){
fileList[fileList.length] = item;
}
getDataTransfer = function(event) {
var dataTransfer;
return dataTransfer = event.dataTransfer || event.originalEvent.dataTransfer;
};
processDragOverOrEnter = function(event) {
if (event != null) {
event.preventDefault();
}
getDataTransfer(event).effectAllowed = 'copy';
element.addClass(attrs.overClass); // console.log(element);
return false;
};
validMimeTypes = attrs.fileDropzone;
checkSize = function(size) {
var _ref;
if (((_ref = attrs.maxFileSize) === (void 0) || _ref === '') || (size / 1024) / 1024 < attrs.maxFileSize) {
return true;
} else {
alert("File must be smaller than " + attrs.maxFileSize + " MB");
return false;
}
};
isTypeValid = function(type) {
if ((validMimeTypes === (void 0) || validMimeTypes === '') || validMimeTypes.indexOf(type) > -1) {
return true;
} else {
alert("Invalid file type. File must be one of following types " + validMimeTypes);
return false;
}
};
element.bind('dragover', processDragOverOrEnter);
element.bind('dragenter', processDragOverOrEnter);
return element.bind('drop', function(event) {
var files;
if (event != null) {
event.preventDefault();
}
element.removeClass(attrs.overClass);
fileList = [];
files = getDataTransfer(event).files;
for(var i = 0; i < files.length; i++){
if(!isTypeValid(files[i].type))
return false;
if(!checkSize(files[i].size))
return false;
/* var reader = new FileReader();
reader.onload = function(reader,evt){
console.log(reader);
};
reader.readAsDataURL(files[i]);*/
/* fileReader.readMyAsDataURL(files[i],scope).then(
function(ret){
console.log(ret);
});*/
fileReader.readMyAsDataURL(files[i], scope)
.then(function(ret) {
var file = {
isSuccess: false,
isCancel: false,
isError: false,
progress: 0,
isReady: false,
isUploading: false,
file: ret.srcfile,
stream: ret.stream,
upload: function (item) { var options = {
headers: {'Content-Type': undefined},
callbackError: function(args,data){
item.isError = true;
},
callbackSuccess: function(args,data){
item.isSuccess = true;
item.progress = 100;
console.log(this.isSuccess);
}
};
var addOptions = {
transformRequest: angular.identity
};
var fd = new FormData();
fd.append('file', this.file);
$bjtHttpService.$post('demo/file/upload',fd,options,addOptions);
}
};
addfile(file);
});
}
scope.files = fileList;
return false;
});
}
};
}]);
app.directive('fileModel', ['$parse', '$bjtHttpService', function ($parse, $bjtHttpService) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
var filelist = [];
element.bind('change', function(){
scope.$apply(function(){
for(var i = 0; i < element[0].files.length; i++){
var file = {
isSuccess: false,
isCancel: false,
isError: false,
progress: 0,
isReady: false,
isUploading: false,
file: element[0].files[i],
fileStream: null,
upload: function (item) { var options = {
headers: {'Content-Type': undefined},
callbackError: function(args,data){
item.isError = true;
},
callbackSuccess: function(args,data){
item.isSuccess = true;
item.progress = 100;
console.log(this.isSuccess);
}
};
var addOptions = {
transformRequest: angular.identity
};
var fd = new FormData();
fd.append('file', this.file);
$bjtHttpService.$post('demo/file/upload',fd,options,addOptions);
}
};
filelist[i] = file;
} modelSetter(scope, filelist);
});
});
}
};
}]); app.controller('HugeScreenCtrl', ['$scope', 'fileReader', function($scope, fileReader) { $scope.allprogress=0;
$scope.myFile = '';
$scope.image= null;
$scope.imageFileName = '';
$scope.redColorActive = 'false';//'b-danger';
$scope.removeItem = function(index){
$scope.myFile.splice(index, 1);
};
$scope.getNotUploadedItems = function () {
var files = [];
for(var i = 0, j = 0; i < $scope.myFile.length; i++){
if(!$scope.myFile[i].isSuccess)
files[j++] = $scope.myFile[i];
}
return files;
};
$scope.getImage = function(item){
fileReader.readMyAsDataURL(item, $scope)
.then(function(result) {
return result;
});
};
$scope.uploadAllfiles = function(){
$scope.allprogress = 0.0;
console.log($scope.allprogress); var percent = 0;
if($scope.myFile.length > 0)
percent = 100/$scope.myFile.length;
console.log(percent);
for( var i = 0; i < $scope.myFile.length; i++) {
if($scope.myFile[i].isSuccess)
$scope.allprogress = $scope.allprogress+ percent;
else{
$scope.myFile[i].upload($scope.myFile[i]);
if($scope.myFile[i].isSuccess)
$scope.allprogress = $scope.allprogress+ percent;
}
console.log($scope.allprogress);
}
};
}]);