[angularjs] AngularJS : 멀티 파트 양식으로 간단한 파일 업로드를 구현하는 방법은 무엇입니까?

AngularJS에서 node.js 서버로 간단한 멀티 파트 양식 게시를하고 싶습니다. 양식에는 한 부분에는 JSON 객체가 있고 다른 부분에는 이미지가 있어야합니다 (현재는 $ resource로 JSON 객체 만 게시하고 있습니다)

input type = “file”로 시작해야한다고 생각했지만 AngularJS가 바인딩 할 수 없다는 것을 알았습니다.

내가 찾을 수있는 모든 예제는 드래그 앤 드롭을 위해 jQuery 플러그인을 래핑하는 것입니다. 하나의 파일을 간단하게 업로드하고 싶습니다.

나는 AngularJS를 처음 사용하고 내 지시문을 작성해도 전혀 편안함을 느끼지 않습니다.



답변

angularjs 이외의 다른 종속성이없는 실제 작동 솔루션 (v.1.0.6으로 테스트)

html

<input type="file" name="file" onchange="angular.element(this).scope().uploadFile(this.files)"/>

Angularjs (1.0.6) 는 “입력 파일”태그에서 ng-model 을 지원하지 않으므로 사용자가 선택한 모든 파일을 최종적으로 전달하는 “네이티브 웨이”에서 수행해야합니다.

제어 장치

$scope.uploadFile = function(files) {
    var fd = new FormData();
    //Take the first selected file
    fd.append("file", files[0]);

    $http.post(uploadUrl, fd, {
        withCredentials: true,
        headers: {'Content-Type': undefined },
        transformRequest: angular.identity
    }).success( ...all right!... ).error( ..damn!... );

};

멋진 부분은 정의되지 않은 컨텐츠 유형과 transformRequest : angular.identity로 $ http에 올바른 “컨텐츠 유형”을 선택하고 멀티 파트 데이터를 처리 할 때 필요한 경계를 관리 할 수있는 기능을 제공합니다.


답변

단순 / 경량 ng-file-upload 지시문을 사용할 수 있습니다 . FileAPI 플래시 심으로 HTML5가 아닌 브라우저의 드래그 앤 드롭, 파일 진행 및 파일 업로드를 지원합니다.

<div ng-controller="MyCtrl">
  <input type="file" ngf-select="onFileSelect($files)" multiple>
</div>

JS :

//inject angular file upload directive.
angular.module('myApp', ['ngFileUpload']);

var MyCtrl = [ '$scope', 'Upload', function($scope, Upload) {
  $scope.onFileSelect = function($files) {
  Upload.upload({
    url: 'my/upload/url',
    file: $files,            
  }).progress(function(e) {
  }).then(function(data, status, headers, config) {
    // file is uploaded successfully
    console.log(data);
  }); 

}];


답변

파일을 직접 보내는 것이 더 효율적입니다.

인코딩베이스 64 로는 Content-Type: multipart/form-data추가 33 %의 오버 헤드를 추가한다. 서버가 지원하는 경우 파일을 직접 보내는 것이 더 효율적입니다.

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

File 객체 와 함께 POST를 보낼 때 설정하는 것이 중요합니다 'Content-Type': undefined. XHR의 전송 방법은 다음 감지 File 객체를 자동으로 콘텐츠 형식을 설정합니다.

여러 파일을 보내려면 FileList에서 직접 여러 요청 수행을 참조하십시오.$http.post


input type = “file”로 시작해야한다고 생각했지만 AngularJS가 바인딩 할 수 없다는 것을 알았습니다.

<input type=file>요소는 기본적으로 ng-model 지시문 과 함께 작동하지 않습니다 . 사용자 지정 지시문 이 필요합니다 .

“선택-NG-파일을”지침의 워킹 데모에 맞는지 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="fileArray" multiple>
    
    <h2>Files</h2>
    <div ng-repeat="file in fileArray">
      {{file.name}}
    </div>
  </body>


$http.post 컨텐츠 유형 multipart/form-data

보내야하는 경우 multipart/form-data:

<form role="form" enctype="multipart/form-data" name="myForm">
    <input type="text"  ng-model="fdata.UserName">
    <input type="text"  ng-model="fdata.FirstName">
    <input type="file"  select-ng-files ng-model="filesArray" multiple>
    <button type="submit" ng-click="upload()">save</button>
</form>
$scope.upload = function() {
    var fd = new FormData();
    fd.append("data", angular.toJson($scope.fdata));
    for (i=0; i<$scope.filesArray.length; i++) {
        fd.append("file"+i, $scope.filesArray[i]);
    };

    var config = { headers: {'Content-Type': undefined},
                   transformRequest: angular.identity
                 }
    return $http.post(url, fd, config);
};

FormData API를 사용하여 POST를 보낼 때 설정하는 것이 중요합니다 'Content-Type': undefined. XHR의 송신 방법은 다음으로 감지 FormData오브젝트를 자동적으로 콘텐츠 타입 헤더 설정 다중 / 폼 데이터적절한 경계 .


답변

방금이 문제가있었습니다. 따라서 몇 가지 접근 방식이 있습니다. 첫 번째는 새로운 브라우저가

var formData = new FormData();

지원이 최신 브라우저로 제한되는 방법 에 대한 정보가 포함 된 블로그 링크를 클릭하면 그렇지 않으면이 문제가 완전히 해결됩니다.

그렇지 않으면 대상 속성을 사용하여 양식을 iframe에 게시 할 수 있습니다. 양식을 게시 할 때 표시 속성이 none으로 설정된 대상을 iframe으로 설정해야합니다. 대상은 iframe의 이름입니다. (그냥 알 잖아)

이게 도움이 되길 바란다


답변

이것이 늦은 항목이라는 것을 알고 있지만 간단한 업로드 지시문을 만들었습니다. 당신은 곧 일할 수 있습니다!

<input type="file" multiple ng-simple-upload web-api-url="/api/post"
       callback-fn="myCallback" />

Web API를 사용하는 예제를 통해 Github에서 더 간단하게 업로드 할 수 있습니다 .


답변

다음 과 같이 $resource리소스의 params 속성에 데이터를 할당하여 업로드 할 수 있습니다 actions.

$scope.uploadFile = function(files) {
    var fdata = new FormData();
    fdata.append("file", files[0]);

    $resource('api/post/:id', { id: "@id" }, {
        postWithFile: {
            method: "POST",
            data: fdata,
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }
        }
    }).postWithFile(fdata).$promise.then(function(response){
         //successful 
    },function(error){
        //error
    });
};


답변

방금 AngularJs의 간단한 업 로더에 대한 간단한 지시문 (기존의 내용 중 하나에서)을 작성했습니다.

(정확한 jQuery 업 로더 플러그인은 https://github.com/blueimp/jQuery-File-Upload입니다 )

AngularJ를 사용하는 간단한 업 로더 (CORS 구현)

(서버 측은 PHP 용이지만 노드를 간단하게 변경할 수도 있습니다)