AngularJSからnode.jsサーバーへの単純なマルチパートフォームの投稿を行いたいのですが、フォームには一方の部分にJSONオブジェクト、もう一方の部分に画像を含める必要があります(現在、$ resourceのJSONオブジェクトのみを投稿しています)。
私はinput type = "file"から始めるべきだと考えましたが、その後AngularJSはそれにバインドできないことがわかりました。
私が見つけることができるすべての例はドラッグ&ドロップのためにjQueryプラグインをラップするためのものです。 1つのファイルを簡単にアップロードしたいのですが。
私はAngularJSに慣れていないので、自分自身のディレクティブを書くことにまったく不安を感じません。
Angularjs以外の依存関係のない実際の実用的なソリューション(v.1.0.6でテスト済み)
html
<input type="file" name="file" onchange="angular.element(this).scope().uploadFile(this.files)"/>
Angularjs(1.0.6)は "input-file"タグでng-modelをサポートしていないので、すべてを(最終的に)渡す "native-way"で行う必要があります。ユーザーから選択したファイル。
コントローラー
$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!... );
};
クールな部分は、未定義のcontent-typeと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);
});
}];
Content-Type: multipart/form-data
の base64エンコーディング は、さらに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-model
で動作する "select-ng-files"ディレクティブの実用的なデモ1angular.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
オブジェクトを検出し、コンテンツタイプヘッダを自動的に multipart/form-dataに設定します。 と の適切な境界 。
私はこの問題を抱えています。だからいくつかのアプローチがあります。 1つ目は、新しいブラウザが
var formData = new FormData();
このリンクをたどって 現代のブラウザにどのようにサポートが制限されているかについての情報があるブログをたどってください、そうでなければそれは完全にこの問題を解決します。
それ以外の場合は、target属性を使用してフォームをiframeに投稿できます。フォームを投稿するときは、必ずdisplayプロパティをnoneに設定してターゲットをiframeに設定してください。ターゲットはiframeの名前です。 (ちょうどあなたが知っているので。)
これが役立つことを願っています
私はこれが遅いエントリであることを知っていますが、私は簡単なアップロードディレクティブを作成しました。あなたはすぐに働くことができます!
<input type="file" multiple ng-simple-upload web-api-url="/api/post"
callback-fn="myCallback" />
ng-simple-upload GithubについてさらにWeb APIを使った例で説明します。
次のように、データをリソースactions
のparams属性に割り当てることで、$resource
経由でアップロードできます。
$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用ですが、ノードも簡単に変更できます)
代替案を追加したいと思います。角度ファイルアップロードを利用する。説明があります。
あなたはここで詳細な説明を見つけることができます: https://github.com/nervgh/angular-file-upload 例: https://github.com/nervgh/angular-file-upload/tree/master/examples/simple