file
(ファイルシステムファイル)とdata
(JSONオブジェクト)の2つの部分で構成されるマルチパートHTTPリクエストを送信する必要があるAPIエンドポイントがあります。
いくつかの調査の後、AngularJSでマルチパートリクエストを行う方法を見つけました。
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
data: model,
file: file
},
transformRequest: customFormDataObject
});
1)customFormDataObject
関数の初期形式は次のとおりです。
customFormDataObject formDataObject = function (data, headersGetter) {
var fd = new FormData();
angular.forEach(data, function (value, key) {
fd.append(key, value);
});
var headers = headersGetter();
delete headers['Content-Type'];
return fd;
};
この実装の結果は、リクエストの個々の部分にcontentType
が設定されていないことです。
2)さらに読んだ後( https://stackoverflow.com/a/24535293/689216 ) Blob、このように見えるcustomFormData
オブジェクト(ちょっとした混乱、基本的に最初の部分はcontentType
application/json
、2番目のimage/png
):
customFormDataObject = function (data, headersGetter) {
var fd = new FormData();
var contentType = 'application/json';
angular.forEach(data, function (value, key) {
fd.append(key, new Blob([JSON.stringify(value)], {
type: contentType
}));
contentType = 'image/png';
});
var headers = headersGetter();
delete headers['Content-Type'];
return fd;
};
この2番目のアプローチは、リクエストの各部分に正しいcontentType
を設定しますが、部分に値を設定しません。
基本的に何が起こるかは1)で、正しい値はマルチパートに設定されますが、contentType
は設定されません。 2)では、contentType
が設定されますが、マルチパートの値は設定されません。
何か不足していますか?この機能はこのように動作するはずではありませんか?
ありがとう!
Angularでファイルをアップロードする最も簡単な方法:
var fd = new FormData();
fd.append('file', file);
fd.append('data', 'string');
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
絶対に不可欠なのは、configオブジェクトの次の2つのプロパティです。
transformRequest: angular.identity
angularのデフォルトのシリアル化をオーバーライドし、データをそのまま残します。
headers: {'Content-Type': undefined }
ブラウザが正しいContent-Type
をmultipart/form-data
として検出し、正しい境界を埋めるようにします。
私のために他に何も働いていません! Lady Louthan's wonderful blogpost のご厚意による。
まったく同じ問題を解決するだけです。
いくつかのテストの後、あなたが説明したこの状況がありました:
基本的に1で何が起こるか)正しい値はマルチパートに設定されますが、contentTypeは設定されません。 2)では、contentTypeが設定されますが、マルチパートの値は設定されません。
この問題を解決するには、Blobと$ http Postの代わりにPost Ajaxを使用する必要がありました。
この場合、$ httpは正しく機能しないようです。
コード:
var formData = new FormData();
var blobId = new Blob([100], { 'type':'text/plain' });
formData.append('testId', blobId);
var blobImage = fileService.base64ToBlob(contentToDecode, 'image/jpeg');
formData.append('file', blobImage, 'imagem' + (i + 1) + '.jpg');
リクエスト:
$.ajax({
url: url,
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(response) {
deferred.resolve(response);
$rootScope.requestInProgress = false;
},
error: function(error) {
deferred.reject(error);
$rootScope.requestInProgress = false;
}
});
このようなことを試しましたか:
$httpProvider.defaults.transformRequest = function(data) {
if (data === undefined){
return data;
}
var formData = new FormData();
for (var key in data){
if(typeof data[key] == 'object' && !(data[key] instanceof File)){
formData.append(key, JSON.stringify(data[key]));
}else{
formData.append(key, data[key]);
}
}
return formData;
};
https://github.com/danialfarid/ng-file-upload/ を使用できます。
このファイルアップローダーには、上記の質問で述べたように、ファイルとデータ(JSON形式)を別々に送信するための規定があります。
例:-
var upload = $upload.upload({
url: url,
file: file,
method: 'POST' or 'PUT', default POST,
headers: {'Content-Type': 'multipart/form-data'}, // only for html5
fileName: 'doc.jpg',
fileFormDataName: 'myFile',
data: {'data': model}
});
上記のコードでは、POSTまたはPUTリクエストを 'multipart/form-data'、ファイル、およびデータオブジェクトと共にJSONとして個別に送信できます。
詳細については、上記のリンクにアクセスして、プラグインのReadMe.mdをご覧ください。
私のアプローチは現在フォローしているアプローチとは少し異なりますが、目的は同じです。
これを解決するためにやったことは。
var formData = new FormData(document.getElementById('myFormId'));
それから私のサービスで
var deferred = $q.defer();
$http.post('myurl', formData, {
cache: false,
contentType: false,
processData: false,
})
.success(function (response) {
deferred.resolve(response);
})
.error(function (reject) {
deferred.reject(reject);
});
return deferred.promise;