AngularJS 的多部分请求

Multipart request with AngularJS

我有一个 API 端点,我必须向其发送多部分 HTTP 请求,该请求由两部分组成,file(一个文件系统文件)和 data(一个 JSON对象)。

经过一番研究,我发现了如何在 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) 阅读更多内容后 () 我尝试为此使用 BlobcustomFormData 对象看起来像这样(有点乱,基本上第一部分是 contentType application/json,第二部分是 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;
 };

第二种方法为请求的每个部分设置了正确的 contentType,但它没有为这些部分设置任何值。

基本上 1) 在多部分中设置了正确的值,但未设置 contentType。使用 2) 设置 contentType,但不设置多部分的值。

我错过了什么吗?这个功能不应该像这样工作吗?

谢谢!

你有没有尝试过这样的事情:

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

在上面的代码中,您可以发送带有 'multipart/form-data' 的 POST 或 PUT 请求,文件和数据对象分别作为 JSON。

更多信息可以访问上面的link并查看插件的ReadMe.md

我知道我的方法与您目前采用的方法略有不同,但 objective 是相同的。

我刚刚解决了完全相同的问题。

经过一些测试,我遇到了您描述的这种情况:

基本上发生的情况是 1) 在多部分中设置了正确的值,但未设置 contentType。 2) 设置了 contentType,但没有设置多部分的值。

为了解决这个问题,我不得不使用 Blob 和 Post Ajax 而不是 $http Post .

在这种情况下 $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;
      }
    });

我解决这个问题的方法是。

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;

在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(){
});

绝对必要的是配置对象的以下两个属性:

transformRequest: angular.identity

覆盖 Angular 的默认序列化,使我们的数据保持完整。

headers: {'Content-Type': undefined }

让浏览器将正确的 Content-Type 检测为 multipart/form-data,并填写正确的边界。

没有别的对我有用!由 Louthan 夫人 wonderful blogpost 提供。