Angular js/MVC 中的文件拖放功能不起作用

Posted

技术标签:

【中文标题】Angular js/MVC 中的文件拖放功能不起作用【英文标题】:File drag and drop functionality in Angular js/MVC not working 【发布时间】:2018-01-26 02:38:07 【问题描述】:

我正在尝试在 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 我也看到该组件存在完全相同的问题。

【问题讨论】:

【参考方案1】:

编辑:

为 pdf 预览更新了答案。代码在同一个 plunker 中可用。

参考:@Michael https://***.com/a/21732039/6347317 的出色解决方案

在上面的示例中,来自 http POST 的响应用于“new Blob([response]”。在 angular-file-upload 库中,“response”将是“uploader.xml”中的“fileItem._file”属性。 onAfterAddingFile”函数。可以通过控制台日志查看这些数据,以便更好地理解。

另外请注意,如果 PDf 查看器未在 chrome 中启用,则必须使用以下命令启用它:https://support.google.com/chrome/answer/6213030?hl=en

结束编辑

既然你提到你尝试使用 angular-file-upload 库,我已经用它创建了一个 plunker:

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 个文件。

请检查一下,如果您对代码有任何疑问,请告诉我。

【讨论】:

感谢 vijay,但我仍然看到同样的问题,我注意到当我尝试在纯 html 文件中运行代码并在没有 visualstudio/iis 的情况下运行时,文件被丢弃在网页上并且它可以工作,但是当我在 Visual Studio/iis 中运行相同的代码时,我看到了上述奇怪的问题 哦,好的。那么它可能是在 Visula Studio 中的一些设置。你是如何在 Visual Studio 中打开网页的?看到这个链接:***.com/questions/15226600/… 不确定是否是这样,但请您查看帖子底部的解决方案。可能只是 Visual Studio 是 Visual Studio:devexpress.com/Support/Center/Question/Details/T520060/… 我没有使用 Visual Studio 作为 IDE。我主要使用 Sublime Text 。由于您怀疑它是 Visual Studio 问题,您是否可以选择将 IDE 切换到其他东西?如果是,请这样做。否则,恐怕我没有更多的建议了,因为这样的代码工作正常。 嗨 vijay 所以最后我们决定使用角度文件上传。但我们也想实现 pdf 预览功能,您能告诉我们如何实现吗?任何信息都会有所帮助

以上是关于Angular js/MVC 中的文件拖放功能不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用 angular4 的拖放事件在 IE11 中不起作用

WPF中的拖放文件不起作用

Angular 嵌套拖放 / CDK 材质 cdkDropListGroup cdkDropList nested

角度拖放列表简单演示不起作用

用于 Angular 行重新排序的 Kendo Grid - Angular 4/5 - HTML5 拖放 API

fullCalendar 中的拖放事件不起作用