【问题标题】:Upload multipart form data with filename in Request Payload在请求有效负载中上传带有文件名的多部分表单数据
【发布时间】:2015-08-14 09:12:52
【问题描述】:

我仍然对上传文件的不同方法感到困惑。后端服务器不在我的控制之下,但我可以使用 Swagger 页面或 Postman 上传文件。这意味着服务器运行正常。但是当我使用 AngularJS 进行上传时,它不起作用。

这是使用 Postman 进行测试的方法。我只是用form-data:

请注意,请求标头的 Content-Type 为 multipart/form-data。但是 Request Payload 有 filename 和 Content-Type as image/png。

这是我的代码:

$http({
  method: 'POST',
  url: ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC',
  headers: { 'Content-Type': undefined },
  transformRequest: function(data) { 
    var fd = new FormData();
    fd.append('file', params.imageData);
    return fd; 
  }
})

params 只是一个在imageData 中有文件url 的对象。

我的代码也发送了类似的 URL 参数(因此我们可以忽略导致问题的原因)。但是请求有效负载是 base64 并且它看起来不同,因为它缺少 filename 字段。

我对后端的控制为零,它是用 .NET 编写的。

所以我想我的问题是:使用 Angular($http 或 $resource),我如何修改请求,以便像 Postman 那样发送正确的请求有效负载?我不知道如何对此进行逆向工程。

我已经尝试过这个https://github.com/danialfarid/ng-file-upload,它实际上在 POST 之前首先做了 OPTIONS 请求(假设 CORS 问题)。但是服务器给了 OPTIONS 405 错误。

【问题讨论】:

  • 您需要一个实际的File(或只是一个Blob)对象来发送以在第一个请求中获得效果,params.imageData 是一个字符串。
  • params.imageData 只是来自input type=filefile:// URL。或者你的意思是我没有想到的其他东西?
  • 您发布的params.imageData 是一个base64 编码的png,它是一个字符串。要让 FormData 以您希望的方式发布数据,它必须是 File 对象或 Blob 对象。 Ifd.append('file', blob_from_imageData); 搜索 SO 以将数据 url 转换为 blob。
  • 你是怎么解决的?面临同样的问题。请帮忙!

标签: angularjs file-upload angular-file-upload


【解决方案1】:

您可以使用以下方式:

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

在你的代码中:

$scope.uploadFile = function(files) {
    var fd = new FormData();
    //Take the first selected file
    fd.append("file", files[0]);
    var uploadUrl = ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC';
    $http.post(uploadUrl, fd, {
        withCredentials: true,
        headers: {'Content-Type': undefined },
        transformRequest: angular.identity
    }).success( ...all right!... ).error( ..damn!... );

};

【讨论】:

    【解决方案2】:

    我的需要是追随者。

    • 表单中有默认图片。
    • 单击图片打开文件选择窗口。
    • 当用户选择一个文件时,它会立即上传到服务器。
    • 一旦我收到文件有效的响应,就会向用户显示图片而不是默认图片,并在其旁边添加一个删除按钮。
    • 如果用户单击现有图片,文件选择窗口将重新打开。

    我尝试使用github上的一些代码sn-ps并没有解决问题,但是以正确的方式引导我,而我最终做的事情是这样的:

    指令

    angular.module("App").directive('fileModel', function ($parse) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                scope.files = {};
                var model = $parse(attrs.fileModel);
                var modelSetter = model.assign;
    
                // I wanted it to upload on select of file, and display to the user.
                element.bind('change', function () {
                    scope.$apply(function () {
                        modelSetter(scope, element[0].files[0]);
                    });
    
                    // The function in the controller that uploads the file.
                    scope.uploadFile();
                });
            }
        };
    });
    

    HTML

    <div class="form-group form-md-line-input">
        <!-- A remove button after file has been selected -->
        <span class="icon-close pull-right"
              ng-if="settings.profile_picture"
              ng-click="settings.profile_picture = null"></span>
        <!-- Show the picture on the scope or a default picture -->
        <label for="file-pic">
            <img ng-src="{{ settings.profile_picture || DefaultPic }}"
                 class="clickable" width="100%">
        </label>
    
        <!-- The actual form field for the file -->
        <input id="file-pic" type="file" file-model="files.pic" style="display: none;" />
    </div>
    

    控制器

    $scope.DefaultPic = '/default.png';
    
    $scope.uploadFile = function (event) {
            var filename = 'myPic';
            var file = $scope.files.pic;
            var uploadUrl = "/fileUpload";
    
            file('upfile.php', file, filename).then(function (newfile) { 
                $scope.settings.profile_picture = newfile.Results;
                $scope.files = {};
            });
    };
    
    function file(q, file, fileName) {
        var fd = new FormData();
        fd.append('fileToUpload', file);
        fd.append('fn', fileName);
        fd.append('submit', 'ok');
    
        return $http.post(serviceBase + q, fd, {
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }
        }).then(function (results) {
            return results.data;
        });
    }
    

    希望对你有帮助。

    附:此示例中删除了很多代码,如果您需要澄清,请发表评论。

    【讨论】:

      猜你喜欢
      • 2014-06-01
      • 2016-06-29
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多