使用请求有效载荷上传带有文件名的多部分表单数据

8
我仍然对上传文件的不同方法感到困惑。后端服务器不在我的控制之下,但我可以使用Swagger页面或Postman上传文件。这意味着服务器正常工作。但是当我使用AngularJS进行上传时,它无法正常工作。
以下是使用Postman测试的有效方法。我只使用了“form-data”:
注意,请求头中的Content-Type为multipart/form-data。但请求有效负载具有filename和Content-Type作为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字段,因此看起来不同。

enter image description here

我无法控制后端,它是用.NET编写的。

所以我的问题是:使用Angular($http或$resource),如何修改请求,以便像Postman一样发送正确的请求有效负载?我无法逆向工程这个问题。

我尝试过使用https://github.com/danialfarid/ng-file-upload,它实际上在POST之前进行了OPTIONS请求(假设是CORS问题)。但服务器返回了405错误。


您需要一个实际的File(或者仅仅是一个Blob)对象来发送到第一次请求中以获得效果,params.imageData是一个字符串。 - Musa
params.imageData只是来自于input type=filefile://URL。或者你指的是我没有想到的其他东西? - HP.
1
从您发布的内容来看,params.imageData 是一个 base64 编码的 png 图像,是一个字符串。为了以所需的方式提交数据,它必须是一个 File 对象或 Blob 对象。您可以通过搜索 SO 来寻找将数据 URL 转换为 Blob 的问题,并使用 fd.append('file', blob_from_imageData); 将其添加到 FormData 中。 - Musa
你是怎么解决的?我也遇到了同样的问题。请帮忙! - Progga Ilma
2个回答

2
你可以使用类似以下的内容:

您可以使用以下内容之一:

<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!... );

};

0

我的需求如下:

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

我尝试使用了一些在Github上的代码片段,但没有解决问题,但指导了我正确的方向。最终我做的是:

指令

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>

Controller

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

希望能有所帮助。
另外,由于篇幅限制,这个示例中删除了很多代码,如果您需要澄清,请在评论中说明。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接