web-dev-qa-db-ja.com

Angularjsマルチパートフォームデータとファイルをアップロードする方法は?

Angular.jsの初心者ですが、基本をよく理解しています。

私がやろうとしているのは、ファイルとフォームデータをマルチパートフォームデータとしてアップロードすることです。これは角度の機能ではないことを読みましたが、サードパーティのライブラリはこれを行うことができます。 gitを使用して、angular-file-uploadのクローンを作成しましたが、まだ簡単なフォームとファイルを投稿できません。

誰かがこれを行う方法の例、html、jsを提供できますか?

31
CodingIsAwesome

まず第一に

  1. 構造に特別な変更を加える必要はありません。つまり、html入力タグです。
<input accept="image/*" name="file" ng-value="fileToUpload"
       value="{{fileToUpload}}" file-model="fileToUpload"
       set-file-data="fileToUpload = value;" 
       type="file" id="my_file" />

1.2独自のディレクティブを作成し、

.directive("fileModel",function() {
        return {
                restrict: 'EA',
                scope: {
                        setFileData: "&"
                },
                link: function(scope, ele, attrs) {
                        ele.on('change', function() {
                                scope.$apply(function() {
                                        var val = ele[0].files[0];
                                        scope.setFileData({ value: val });
                                });
                        });
                }
        }
})
  1. $ httpProviderを使用したモジュールで、multipart/form-dataに(Accept、Content-Typeなど)のような依存関係を追加します。 (提案は、JSON形式での応答を受け入れます)たとえば:

$ httpProvider.defaults.headers.post ['Accept'] = 'application/json、text/javascript'; $ httpProvider.defaults.headers.post ['Content-Type'] = 'multipart/form-data ; charset = utf-8 ';

  1. 次に、コントローラで別の関数を作成して、フォーム送信呼び出しを処理します。以下のコードのように:

  2. サービス関数では、サーバーが「byteerror」をスローしないように、「responseType」パラメーターを意図的に処理します。

  3. transformRequest。IDが添付された要求形式を変更します。

  4. withCredentials:false、HTTP認証情報の場合。

in controller:

  // code this accordingly, so that your file object 
  // will be picked up in service call below.
  fileUpload.uploadFileToUrl(file); 


in service:

  .service('fileUpload', ['$http', 'ajaxService',
    function($http, ajaxService) {

      this.uploadFileToUrl = function(data) {
        var data = {}; //file object 

        var fd = new FormData();
        fd.append('file', data.file);

        $http.post("endpoint server path to whom sending file", fd, {
            withCredentials: false,
            headers: {
              'Content-Type': undefined
            },
            transformRequest: angular.identity,
            params: {
              fd
            },
            responseType: "arraybuffer"
          })
          .then(function(response) {
            var data = response.data;
            var status = response.status;
            console.log(data);

            if (status == 200 || status == 202) //do whatever in success
            else // handle error in  else if needed 
          })
          .catch(function(error) {
            console.log(error.status);

            // handle else calls
          });
      }
    }
  }])
<script src="//unpkg.com/angular/angular.js"></script>
22
Prasad Shinde

これはプロジェクトのデモページのコピーである必要があり、フォームの送信時にアップロードの進行状況を示す単一のファイルのアップロードを示しています。

(function (angular) {
'use strict';

angular.module('uploadModule', [])
    .controller('uploadCtrl', [
        '$scope',
        '$upload',
        function ($scope, $upload) {
            $scope.model = {};
            $scope.selectedFile = [];
            $scope.uploadProgress = 0;

            $scope.uploadFile = function () {
                var file = $scope.selectedFile[0];
                $scope.upload = $upload.upload({
                    url: 'api/upload',
                    method: 'POST',
                    data: angular.toJson($scope.model),
                    file: file
                }).progress(function (evt) {
                    $scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total, 10);
                }).success(function (data) {
                    //do something
                });
            };

            $scope.onFileSelect = function ($files) {
                $scope.uploadProgress = 0;
                $scope.selectedFile = $files;
            };
        }
    ])
    .directive('progressBar', [
        function () {
            return {
                link: function ($scope, el, attrs) {
                    $scope.$watch(attrs.progressBar, function (newValue) {
                        el.css('width', newValue.toString() + '%');
                    });
                }
            };
        }
    ]);
 }(angular));

HTML

<form ng-submit="uploadFile()">
   <div class="row">
         <div class="col-md-12">
                  <input type="text" ng-model="model.fileDescription" />
                  <input type="number" ng-model="model.rating" />
                  <input type="checkbox" ng-model="model.isAGoodFile" />
                  <input type="file" ng-file-select="onFileSelect($files)">
                  <div class="progress" style="margin-top: 20px;">
                    <div class="progress-bar" progress-bar="uploadProgress" role="progressbar">
                      <span ng-bind="uploadProgress"></span>
                      <span>%</span>
                    </div>
                  </div>

                  <button button type="submit" class="btn btn-default btn-lg">
                    <i class="fa fa-cloud-upload"></i>
                    &nbsp;
                    <span>Upload File</span>
                  </button>
                </div>
              </div>
            </form>

編集:ファイル投稿でサーバーにモデルを渡すことを追加しました。

入力要素のフォームデータは、投稿のデータプロパティで送信され、通常のフォーム値として利用可能になります。

21
Jon

ファイルを直接送信する方が効率的です。

base64 encoding of Content-Type: multipart/form-dataは、33%の余分なオーバーヘッドを追加します。サーバーがサポートしている場合、ファイルを直接送信する方が効率的です:

FileList から複数の$http.postリクエストを直接行う

$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);
};

ファイルオブジェクト でPOSTを送信する場合、'Content-Type': undefinedを設定することが重要です。 XHR send methodFileオブジェクト を検出し、コンテンツタイプを自動的に設定します。


ng-modelで機能する「select-ng-files」ディレクティブの作業デモ1

<input type=file>要素は、デフォルトでは ng-modelディレクティブ では機能しません。 カスタムディレクティブ が必要です。

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>
2
georgeawg

画像とフォームデータを完全に送信するためのこのメソッドを確認できます

<div class="form-group ml-5 mt-4" ng-app="myApp" ng-controller="myCtrl">
                    <label for="image_name">Image Name:</label>
                    <input type="text"   placeholder="Image name" ng-model="fileName" class="form-control" required>
                    <br>

                    <br>
                    <input id="file_src" type="file"   accept="image/jpeg" file-input="files"   >
                    <br>
                        {{file_name}}
            <img class="rounded mt-2 mb-2 " id="prvw_img" width="150" height="100" >
                    <hr>
                      <button class="btn btn-info" ng-click="uploadFile()">Upload</button>
                        <br>

                       <div ng-show = "IsVisible" class="alert alert-info w-100 shadow mt-2" role="alert">
              <strong> {{response_msg}} </strong>
            </div>
                            <div class="alert alert-danger " id="filealert"> <strong> File Size should be less than 4 MB </strong></div>
                    </div>

Angular JS Code

    var app = angular.module("myApp", []);
 app.directive("fileInput", function($parse){
      return{
           link: function($scope, element, attrs){
                element.on("change", function(event){
                     var files = event.target.files;


                     $parse(attrs.fileInput).assign($scope, element[0].files);
                     $scope.$apply();
                });
           }
      }
 });
 app.controller("myCtrl", function($scope, $http){
      $scope.IsVisible = false;
      $scope.uploadFile = function(){
           var form_data = new FormData();
           angular.forEach($scope.files, function(file){
                form_data.append('file', file); //form file
                                form_data.append('file_Name',$scope.fileName); //form text data
           });
           $http.post('upload.php', form_data,
           {
                //'file_Name':$scope.file_name;
                transformRequest: angular.identity,
                headers: {'Content-Type': undefined,'Process-Data': false}
           }).success(function(response){
             $scope.IsVisible = $scope.IsVisible = true;
                      $scope.response_msg=response;
               // alert(response);
               // $scope.select();
           });
      }

 });
0