J'ai un point de terminaison API auquel je dois envoyer une requête HTTP en plusieurs parties, composée de deux parties, file
(un fichier de système de fichiers) et data
(un objet JSON).
Après quelques recherches, j'ai découvert comment faire une demande en plusieurs parties dans AngularJS:
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
data: model,
file: file
},
transformRequest: customFormDataObject
});
1) La fonction customFormDataObject
avait initialement cette forme:
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;
};
Le résultat de cette implémentation est que les parties individuelles de la demande n'ont pas de contentType
défini.
2) Après avoir lu un peu plus ( https://stackoverflow.com/a/24535293/689216 ) J'ai essayé d'utiliser un Blob pour cela, l'objet customFormData
ressemblant à ceci (un peu en désordre, fondamentalement la première partie sera de contentType
application/json
, le deuxième 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;
};
Cette deuxième approche définit le contentType
correct pour chaque partie de la demande, mais elle ne définit aucune valeur pour les parties.
Fondamentalement, ce qui se passe est avec 1) les valeurs correctes sont définies dans les parties multiples, mais les contentType
ne sont pas définies. Avec 2) les contentType
sont définis, mais pas les valeurs pour les parties multiples.
Suis-je en train de manquer quelque chose? Cette fonctionnalité n'est-elle pas censée fonctionner comme ça?
Merci!
La façon la plus simple de télécharger des fichiers dans 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(){
});
Les deux propriétés suivantes de l'objet config sont absolument essentielles:
transformRequest: angular.identity
remplace la sérialisation par défaut d'Angular, laissant nos données intactes.
headers: {'Content-Type': undefined }
permet au navigateur de détecter la bonne Content-Type
comme multipart/form-data
, et remplissez la limite correcte.
Rien d'autre n'a fonctionné pour moi! Avec l'aimable autorisation de Lady Louthan merveilleux blogpost .
Je résous exactement le même problème.
Après quelques tests, j'ai eu cette situation que vous avez décrite:
Fondamentalement, ce qui se passe avec 1) les valeurs correctes sont définies dans les parties multiples, mais les contentType ne sont pas définis. Avec 2) les contentType sont définis, mais pas les valeurs pour les parties multiples.
Pour résoudre ce problème, j'ai dû utiliser Blob et Post Ajax au lieu de $ http Post.
Il semble que $ http ne fonctionne pas correctement dans ce cas.
Code:
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');
Demande:
$.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;
}
});
Avez-vous essayé quelque chose comme ça:
$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;
};
Vous pouvez utiliser https://github.com/danialfarid/ng-file-upload/ .
Dans ce programme de téléchargement de fichiers, il est prévu d'envoyer le fichier et les données (au format JSON) séparément, comme vous l'avez mentionné dans votre question ci-dessus.
Pour Ex: -
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}
});
Dans le code ci-dessus, vous pouvez envoyer une demande POST ou PUT avec 'multipart/form-data', fichier et objet de données au format JSON séparément.
Pour plus d'informations, vous pouvez visiter le lien ci-dessus et consulter le fichier ReadMe.md du plug-in.
Je sais que mon approche est un peu différente de celle que vous suivez actuellement, mais l'objectif est le même.
ce que j'ai fait pour résoudre ce problème était.
var formData = new FormData(document.getElementById('myFormId'));
puis à mon service
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;