Angular js/MVC 中的文件拖放功能不起作用
File drag and drop functionality in Angular js/MVC not working
我正在尝试在 Angular js/MVC 中实现简单的文件拖放功能。
我为拖放创建了一个指令。
(function (angular, undefined) {
'use strict';
angular.module('fileupload', [])
.directive("myDirective", function ($parse) {
return {
restrict: 'A',
link: fileDropzoneLink
};
function fileDropzoneLink(scope, element, attrs) {
element.bind('dragover', processDragOverOrEnter);
element.bind('dragenter', processDragOverOrEnter);
element.bind('dragend', endDragOver);
element.bind('dragleave', endDragOver);
element.bind('drop', dropHandler);
var onImageDrop = $parse(attrs.onImageDrop);
//When a file is dropped
var loadFile = function (files) {
scope.uploadedFiles = files;
scope.$apply(onImageDrop(scope));
};
function dropHandler(angularEvent) {
var event = angularEvent.originalEvent || angularEvent;
var files = event.dataTransfer.files;
event.preventDefault();
loadFile(files)
}
function processDragOverOrEnter(angularEvent) {
var event = angularEvent.originalEvent || angularEvent;
if (event) {
event.preventDefault();
}
event.dataTransfer.effectAllowed = 'copy';
element.addClass('dragging');
return false;
}
function endDragOver() {
element.removeClass('dragging');
}
}
});
}(angular));
这是模板
<div class="dropzone" data-my-Directive on-image-drop="$ctrl.fileDropped()">
Drag and drop pdf files here
</div>
这是我的组件代码
(function (angular, undefined) {
'use strict';
angular.module('test', [])
.component('contactUs', contactUs());
function contactUs() {
ContactUs.$inject = ['$scope', '$http'];
function ContactUs($scope, $http) {
var ctrl = this;
ctrl.files = [];
ctrl.services = {
$scope: $scope,
$http: $http,
};
}
//file dropped
ContactUs.prototype.fileDropped = function () {
var ctrl = this;
var files = ctrl.services.$scope.uploadedFiles;
angular.forEach(files, function (file, key) {
ctrl.files.push(file);
});
}
return {
controller: ContactUs,
templateUrl: 'partials/home/contactus/'
};
}
}(angular));
有时拖放操作绝对没有任何问题。但有时我遇到以下问题,拖放不起作用,我得到黑色无效光标。
这个问题是随机的,我在控制台中没有看到任何错误。
而且我还尝试了其他第三方组件,例如 angular-file-upload
https://github.com/nervgh/angular-file-upload 我也看到了与该组件完全相同的问题。
编辑:
为 pdf 预览更新了答案。该代码在同一个 plunker 中可用。
参考资料:@Michael 在
提供的优秀解决方案
在上面的示例中,"new Blob([response]" 中使用了来自 http POST 的响应。在 angular-file-upload 库中,"response" 在 "uploader.onAfterAddingFile" 函数中将是 "fileItem._file" 属性。你可以通过console log查看这些有哪些数据,以便更好的理解。
另请注意,如果在 chrome 中未启用 PDF 查看器,则必须使用以下命令启用它:https://support.google.com/chrome/answer/6213030?hl=en
编辑结束
既然你提到你尝试过 angular-file-upload 库,我已经用它创建了一个插件:
http://plnkr.co/edit/jeYg5fIRaC9wuEYSNOux?p=info
HTML:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script data-require="angular.js@1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-file-upload/2.5.0/angular-file-upload.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div class="col-sm-4">
<h3>Select files</h3>
<div ng-show="uploader.isHTML5">
<!-- 3. nv-file-over uploader="link" over-class="className" -->
<div class="well my-drop-zone" style="width:300px" nv-file-drop nv-file-over="" uploader="uploader"
filters="syncFilter">
<label>
Click here or Drag and Drop file
<input type="file" style="visibility:hidden;" nv-file-select nv-file-over="" uploader="uploader"
filters="syncFilter" multiple/>
</label>
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar" ng-style="{ 'width': uploader.queue[0].progress + '%' }"></div>
</div>
<div>{{uploader.queue[0].file.name}}</div>
<div ng-show="showAlert" class="alert alert-warning alert-dismissable">
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
<strong>Clear the existing file before uploading again!!</strong>
</div>
</div>
</div>
</div>
</body>
</html>
JS:
var app = angular.module('plunker', ['angularFileUpload']);
app.controller('MainCtrl', function($scope,FileUploader) {
var uploader = $scope.uploader = new FileUploader();
// FILTERS
// a sync filter
uploader.filters.push({
name: 'syncFilter',
fn: function(item /*{File|FileLikeObject}*/, options) {
console.log('syncFilter' + this.queue.length);
return this.queue.length < 1;
}
});
// an async filter
uploader.filters.push({
name: 'asyncFilter',
fn: function(item /*{File|FileLikeObject}*/, options, deferred) {
console.log('asyncFilter');
setTimeout(deferred.resolve, 1e3);
}
});
uploader.allowNewFiles = true;
uploader.filters.push({
name:'csvfilter',
fn: function() {
return this.allowNewFiles;
}
});
// CALLBACKS
uploader.onWhenAddingFileFailed = function(item /*{File|FileLikeObject}*/, filter, options) {
console.info('onWhenAddingFileFailed', item, filter, options);
$scope.showAlert=true;
};
uploader.onAfterAddingFile = function(fileItem) {
};
});
它非常简单,我没有得到你提到的错误。我们实际上在我们的一个项目中使用这个库。我还添加了一个过滤器以将上传限制为仅 1 个文件。
请检查一下,如果您对代码有任何疑问,请告诉我。
我正在尝试在 Angular js/MVC 中实现简单的文件拖放功能。
我为拖放创建了一个指令。
(function (angular, undefined) {
'use strict';
angular.module('fileupload', [])
.directive("myDirective", function ($parse) {
return {
restrict: 'A',
link: fileDropzoneLink
};
function fileDropzoneLink(scope, element, attrs) {
element.bind('dragover', processDragOverOrEnter);
element.bind('dragenter', processDragOverOrEnter);
element.bind('dragend', endDragOver);
element.bind('dragleave', endDragOver);
element.bind('drop', dropHandler);
var onImageDrop = $parse(attrs.onImageDrop);
//When a file is dropped
var loadFile = function (files) {
scope.uploadedFiles = files;
scope.$apply(onImageDrop(scope));
};
function dropHandler(angularEvent) {
var event = angularEvent.originalEvent || angularEvent;
var files = event.dataTransfer.files;
event.preventDefault();
loadFile(files)
}
function processDragOverOrEnter(angularEvent) {
var event = angularEvent.originalEvent || angularEvent;
if (event) {
event.preventDefault();
}
event.dataTransfer.effectAllowed = 'copy';
element.addClass('dragging');
return false;
}
function endDragOver() {
element.removeClass('dragging');
}
}
});
}(angular));
这是模板
<div class="dropzone" data-my-Directive on-image-drop="$ctrl.fileDropped()">
Drag and drop pdf files here
</div>
这是我的组件代码
(function (angular, undefined) {
'use strict';
angular.module('test', [])
.component('contactUs', contactUs());
function contactUs() {
ContactUs.$inject = ['$scope', '$http'];
function ContactUs($scope, $http) {
var ctrl = this;
ctrl.files = [];
ctrl.services = {
$scope: $scope,
$http: $http,
};
}
//file dropped
ContactUs.prototype.fileDropped = function () {
var ctrl = this;
var files = ctrl.services.$scope.uploadedFiles;
angular.forEach(files, function (file, key) {
ctrl.files.push(file);
});
}
return {
controller: ContactUs,
templateUrl: 'partials/home/contactus/'
};
}
}(angular));
有时拖放操作绝对没有任何问题。但有时我遇到以下问题,拖放不起作用,我得到黑色无效光标。
这个问题是随机的,我在控制台中没有看到任何错误。
而且我还尝试了其他第三方组件,例如 angular-file-upload https://github.com/nervgh/angular-file-upload 我也看到了与该组件完全相同的问题。
编辑:
为 pdf 预览更新了答案。该代码在同一个 plunker 中可用。
参考资料:@Michael 在
提供的优秀解决方案在上面的示例中,"new Blob([response]" 中使用了来自 http POST 的响应。在 angular-file-upload 库中,"response" 在 "uploader.onAfterAddingFile" 函数中将是 "fileItem._file" 属性。你可以通过console log查看这些有哪些数据,以便更好的理解。
另请注意,如果在 chrome 中未启用 PDF 查看器,则必须使用以下命令启用它:https://support.google.com/chrome/answer/6213030?hl=en
编辑结束
既然你提到你尝试过 angular-file-upload 库,我已经用它创建了一个插件:
http://plnkr.co/edit/jeYg5fIRaC9wuEYSNOux?p=info
HTML:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script data-require="angular.js@1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-file-upload/2.5.0/angular-file-upload.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div class="col-sm-4">
<h3>Select files</h3>
<div ng-show="uploader.isHTML5">
<!-- 3. nv-file-over uploader="link" over-class="className" -->
<div class="well my-drop-zone" style="width:300px" nv-file-drop nv-file-over="" uploader="uploader"
filters="syncFilter">
<label>
Click here or Drag and Drop file
<input type="file" style="visibility:hidden;" nv-file-select nv-file-over="" uploader="uploader"
filters="syncFilter" multiple/>
</label>
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar" ng-style="{ 'width': uploader.queue[0].progress + '%' }"></div>
</div>
<div>{{uploader.queue[0].file.name}}</div>
<div ng-show="showAlert" class="alert alert-warning alert-dismissable">
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
<strong>Clear the existing file before uploading again!!</strong>
</div>
</div>
</div>
</div>
</body>
</html>
JS:
var app = angular.module('plunker', ['angularFileUpload']);
app.controller('MainCtrl', function($scope,FileUploader) {
var uploader = $scope.uploader = new FileUploader();
// FILTERS
// a sync filter
uploader.filters.push({
name: 'syncFilter',
fn: function(item /*{File|FileLikeObject}*/, options) {
console.log('syncFilter' + this.queue.length);
return this.queue.length < 1;
}
});
// an async filter
uploader.filters.push({
name: 'asyncFilter',
fn: function(item /*{File|FileLikeObject}*/, options, deferred) {
console.log('asyncFilter');
setTimeout(deferred.resolve, 1e3);
}
});
uploader.allowNewFiles = true;
uploader.filters.push({
name:'csvfilter',
fn: function() {
return this.allowNewFiles;
}
});
// CALLBACKS
uploader.onWhenAddingFileFailed = function(item /*{File|FileLikeObject}*/, filter, options) {
console.info('onWhenAddingFileFailed', item, filter, options);
$scope.showAlert=true;
};
uploader.onAfterAddingFile = function(fileItem) {
};
});
它非常简单,我没有得到你提到的错误。我们实际上在我们的一个项目中使用这个库。我还添加了一个过滤器以将上传限制为仅 1 个文件。
请检查一下,如果您对代码有任何疑问,请告诉我。