File Upload using AngularJS

前端 未结 29 2022
野趣味
野趣味 2020-11-21 07:24

Here is my HTML form:

相关标签:
29条回答
  • 2020-11-21 07:57

    The <input type=file> element does not by default work with the ng-model directive. It needs a custom directive:

    Working Demo of select-ng-files Directive that Works with ng-model1

    angular.module("app",[]);
    
    angular.module("app").directive("selectNgFiles", function() {
      return {
        require: "ngModel",
        link: function postLink(scope,elem,attrs,ngModel) {
          elem.on("change", function(e) {
            var files = elem[0].files;
            ngModel.$setViewValue(files);
          })
        }
      }
    });
    <script src="//unpkg.com/angular/angular.js"></script>
      <body ng-app="app">
        <h1>AngularJS Input `type=file` Demo</h1>
        
        <input type="file" select-ng-files ng-model="fileList" multiple>
        
        <h2>Files</h2>
        <div ng-repeat="file in fileList">
          {{file.name}}
        </div>
      </body>


    $http.post from a FileList

    $scope.upload = function(url, fileList) {
        var config = { headers: { 'Content-Type': undefined },
                       transformResponse: angular.identity
                     };
        var promises = fileList.map(function(file) {
            return $http.post(url, file, config);
        });
        return $q.all(promises);
    };
    

    When sending a POST with a File object, it is important to set 'Content-Type': undefined. The XHR send method will then detect the File object and automatically set the content type.

    0 讨论(0)
  • 2020-11-21 07:59

    Your file and json data uploading at the same time .

    // FIRST SOLUTION
     var _post = function (file, jsonData) {
                $http({
                    url: your url,
                    method: "POST",
                    headers: { 'Content-Type': undefined },
                    transformRequest: function (data) {
                        var formData = new FormData();
                        formData.append("model", angular.toJson(data.model));
                        formData.append("file", data.files);
                        return formData;
                    },
                    data: { model: jsonData, files: file }
                }).then(function (response) {
                    ;
                });
            }
    // END OF FIRST SOLUTION
    
    // SECOND SOLUTION
    // If you can add plural file and  If above code give an error.
    // You can try following code
     var _post = function (file, jsonData) {
                $http({
                    url: your url,
                    method: "POST",
                    headers: { 'Content-Type': undefined },
                    transformRequest: function (data) {
                        var formData = new FormData();
                        formData.append("model", angular.toJson(data.model));
                    for (var i = 0; i < data.files.length; i++) {
                        // add each file to
                        // the form data and iteratively name them
                        formData.append("file" + i, data.files[i]);
                    }
                        return formData;
                    },
                    data: { model: jsonData, files: file }
                }).then(function (response) {
                    ;
                });
            }
    // END OF SECOND SOLUTION

    0 讨论(0)
  • 2020-11-21 08:00

    You may consider IaaS for file upload, such as Uploadcare. There is an Angular package for it: https://github.com/uploadcare/angular-uploadcare

    Technically it's implemented as a directive, providing different options for uploading, and manipulations for uploaded images within the widget:

    <uploadcare-widget
      ng-model="object.image.info.uuid"
      data-public-key="YOURKEYHERE"
      data-locale="en"
      data-tabs="file url"
      data-images-only="true"
      data-path-value="true"
      data-preview-step="true"
      data-clearable="true"
      data-multiple="false"
      data-crop="400:200"
      on-upload-complete="onUCUploadComplete(info)"
      on-widget-ready="onUCWidgetReady(widget)"
      value="{{ object.image.info.cdnUrl }}"
     />
    

    More configuration options to play with: https://uploadcare.com/widget/configure/

    0 讨论(0)
  • 2020-11-21 08:01
    app.directive('ngUpload', function () {   
      return {    
        restrict: 'A',  
        link: function (scope, element, attrs) {
    
          var options = {};
          options.enableControls = attrs['uploadOptionsEnableControls'];
    
          // get scope function to execute on successful form upload
          if (attrs['ngUpload']) {
    
            element.attr("target", "upload_iframe");
            element.attr("method", "post");
    
            // Append a timestamp field to the url to prevent browser caching results
            element.attr("action", element.attr("action") + "?_t=" + new Date().getTime());
    
            element.attr("enctype", "multipart/form-data");
            element.attr("encoding", "multipart/form-data");
    
            // Retrieve the callback function
            var fn = attrs['ngUpload'].split('(')[0];
            var callbackFn = scope.$eval(fn);
            if (callbackFn == null || callbackFn == undefined || !angular.isFunction(callbackFn))
            {
              var message = "The expression on the ngUpload directive does not point to a valid function.";
              // console.error(message);
              throw message + "\n";
            }                      
    
            // Helper function to create new  i frame for each form submission
            var addNewDisposableIframe = function (submitControl) {
              // create a new iframe
              var iframe = $("<iframe id='upload_iframe' name='upload_iframe' border='0' width='0' height='0' style='width: 0px; height: 0px;
    border: none; display: none' />");
    
              // attach function to load event of the iframe
              iframe.bind('load', function () {
    
                  // get content - requires jQuery
                  var content = iframe.contents().find('body').text();
    
                  // execute the upload response function in the active scope
                  scope.$apply(function () { callbackFn(content, content !== "" /* upload completed */); });
    
                  // remove iframe
                  if (content != "") // Fixes a bug in Google Chrome that dispose the iframe before content is ready.
                    setTimeout(function () { iframe.remove(); }, 250);
    
    
                  submitControl.attr('disabled', null);
                  submitControl.attr('title', 'Click to start upload.');
                });
    
              // add the new iframe to application
              element.parent().append(iframe);
            };
    
            // 1) get the upload submit control(s) on the form (submitters must be decorated with the 'ng-upload-submit' class)
            // 2) attach a handler to the controls' click event
            $('.upload-submit', element).click(
              function () {
    
                addNewDisposableIframe($(this) /* pass the submit control */);
    
                scope.$apply(function () { callbackFn("Please wait...", false /* upload not completed */); });
    
    
    
                var enabled = true;
                if (options.enableControls === null || options.enableControls === undefined || options.enableControls.length >= 0) {
                  // disable the submit control on click
                  $(this).attr('disabled', 'disabled');
                  enabled = false;
                }
    
                $(this).attr('title', (enabled ? '[ENABLED]: ' : '[DISABLED]: ') + 'Uploading, please wait...');
    
                // submit the form
                $(element).submit();
              }
            ).attr('title', 'Click to start upload.');
          }
          else
            alert("No callback function found on the ngUpload directive.");     
        }   
      }; 
    });
    
    
    
    <form class="form form-inline" name="uploadForm" id="uploadForm"
    ng-upload="uploadForm12"  action="rest/uploadHelpFile"  method="post"
    enctype="multipart/form-data" style="margin-top: 3px;margin-left:
    6px"> <button type="submit" id="mbUploadBtn" class="upload-submit"
    ng-hide="true"></button> </form>
    
    @RequestMapping(value = "/uploadHelpFile", method =
    RequestMethod.POST)   public @ResponseBody String
    uploadHelpFile(@RequestParam(value = "file") CommonsMultipartFile[]
    file,@RequestParam(value = "fileName") String
    fileName,@RequestParam(value = "helpFileType") String
    helpFileType,@RequestParam(value = "helpFileName") String
    helpFileName) { }
    
    0 讨论(0)
  • 2020-11-21 08:03

    I am able to upload files using AngularJS by using below code:

    The file for the argument that needs to be passed for the function ngUploadFileUpload is $scope.file as per your question.

    The key point here is to use transformRequest: []. This will prevent $http with messing with the contents of the file.

           function getFileBuffer(file) {
                var deferred = new $q.defer();
                var reader = new FileReader();
                reader.onloadend = function (e) {
                    deferred.resolve(e.target.result);
                }
                reader.onerror = function (e) {
                    deferred.reject(e.target.error);
                }
    
                reader.readAsArrayBuffer(file);
                return deferred.promise;
            }
    
            function ngUploadFileUpload(endPointUrl, file) {
    
                var deferred = new $q.defer();
                getFileBuffer(file).then(function (arrayBuffer) {
    
                    $http({
                        method: 'POST',
                        url: endPointUrl,
                        headers: {
                            "accept": "application/json;odata=verbose",
                            'X-RequestDigest': spContext.securityValidation,
                            "content-length": arrayBuffer.byteLength
                        },
                        data: arrayBuffer,
                        transformRequest: []
                    }).then(function (data) {
                        deferred.resolve(data);
                    }, function (error) {
                        deferred.reject(error);
                        console.error("Error", error)
                    });
                }, function (error) {
                    console.error("Error", error)
                });
    
                return deferred.promise;
    
            }
    
    0 讨论(0)
  • 2020-11-21 08:04

    I tried all alternatives that @Anoyz (Correct answer) gives... and the best solution is https://github.com/danialfarid/angular-file-upload

    Some Features:

    • Progress
    • Multifiles
    • Fields
    • Old browsers (IE8-9)

    It's work fine for me. You just have to pay attention to instructions.

    In server-side i use NodeJs, Express 4 and Multer middleware to manage multipart request.

    0 讨论(0)
提交回复
热议问题