Angularjs $http 发布文件和表单数据

IT技术 javascript angularjs
2021-03-13 01:39:10

我在python中有以下请求

import requests, json, io

cookie = {}
payload = {"Name":"abc"}
url = "/test"
file = "out/test.json"

fi = {'file': ('file', open(file) )}
r = requests.post("http://192.168.1.1:8080" + url, data=payload, files=fi, cookies=cookie)
print(r.text)

将文件和表单字段发送到后端。如何使用 Angular $http 执行相同的操作(发送文件 + 表单字段)。目前,我喜欢这个,但不知道如何发送文件。

var payload = {"Name":"abc"};
$http.post('/test', payload)
    .success(function (res) {
    //success
});
6个回答

当必须同时上传文件和发送用户令牌信息时,我遇到了类似的问题。transformRequest随着形成FormData帮助:

        $http({
            method: 'POST',
            url: '/upload-file',
            headers: {
                'Content-Type': 'multipart/form-data'
            },
            data: {
                email: Utils.getUserInfo().email,
                token: Utils.getUserInfo().token,
                upload: $scope.file
            },
            transformRequest: function (data, headersGetter) {
                var formData = new FormData();
                angular.forEach(data, function (value, key) {
                    formData.append(key, value);
                });

                var headers = headersGetter();
                delete headers['Content-Type'];

                return formData;
            }
        })
        .success(function (data) {

        })
        .error(function (data, status) {

        });

为了获取文件,$scope.file我使用了自定义指令:

app.directive('file', function () {
    return {
        scope: {
            file: '='
        },
        link: function (scope, el, attrs) {
            el.bind('change', function (event) {
                var file = event.target.files[0];
                scope.file = file ? file : undefined;
                scope.$apply();
            });
        }
    };
});

网址:

<input type="file" file="file" required />
这几乎有效...... transformRequest: angular.identity 就是你所需要的。您已经在 data 参数中设置了数据。设置标题: { 'Content-Type': undefined } 就大功告成了。Angular 负责将边界正确附加到内容类型。
2021-04-23 01:39:10
经过多次咬牙切齿后,我得到了它的工作(至少在 chrome 48 和 Angular 1.5.0 中使用 .Net 服务器端和 HttpContext.Request.Files)。您不必将标头设置为 multipart/form-data, XMLHttpRequest 在幕后为您做这件事。设置它实际上会弄乱上传。使用'Content-Type': undefined您也不必删除标题。这允许我通过 .Net HttpContext.Request.Files API 调用来获取文件服务器端
2021-04-26 01:39:10
我同意这应该是公认的答案,因为它允许您在可能需要令牌的情况下使用自己的 API
2021-05-09 01:39:10
作为一种魅力。当只是复制/粘贴工作时,我是多么喜欢。伙计,节省了大量时间。
2021-05-11 01:39:10
Content-Type设置后的删除是为了确保在转换文件时它是表单数据,然后(在准备好进行发布请求之后)它是一个正常的请求Content-Type: application/json
2021-05-13 01:39:10

在发布到 Web.Api 应用程序时,我无法得到 Pavel 的回答。

问题似乎与删除标题有关。

headersGetter();
delete headers['Content-Type'];

为了确保允许浏览器默认 Content-Type 和边界参数,我需要将 Content-Type 设置为 undefined。使用 Pavel 的示例,从未设置边界导致 400 HTTP 异常。

关键是删除删除上面显示的标题的代码,并手动将标题内容类型设置为 null。从而允许浏览器设置属性。

headers: {'Content-Type': undefined}

这是一个完整的例子。

$scope.Submit = form => {
                $http({
                    method: 'POST',
                    url: 'api/FileTest',
                    headers: {'Content-Type': undefined},
                    data: {
                        FullName: $scope.FullName,
                        Email: $scope.Email,
                        File1: $scope.file
                    },
                    transformRequest: function (data, headersGetter) {
                        var formData = new FormData();
                        angular.forEach(data, function (value, key) {
                            formData.append(key, value);
                        });
                        return formData;
                    }
                })
                .success(function (data) {

                })
                .error(function (data, status) {

                });

                return false;
            }

我最近写了一个支持原生多文件上传的指令。我创建的解决方案依赖于一项服务来填补您使用 $http 服务确定的空白。我还包含了一个指令,它为您的 angular module提供了一个简单的 API,用于发布文件和数据。

用法示例:

<lvl-file-upload
    auto-upload='false'
    choose-file-button-text='Choose files'
    upload-file-button-text='Upload files'
    upload-url='http://localhost:3000/files'
    max-files='10'
    max-file-size-mb='5'
    get-additional-data='getData(files)'
    on-done='done(files, data)'
    on-progress='progress(percentDone)'
    on-error='error(files, type, msg)'/>

你可以在 github 上找到代码,在我的博客找到文档

由您来处理 Web 框架中的文件,但我创建的解决方案提供了角度接口来将数据发送到您的服务器。你需要写的angular代码是响应上传事件

angular
    .module('app', ['lvl.directives.fileupload'])
    .controller('ctl', ['$scope', function($scope) {
        $scope.done = function(files,data} { /*do something when the upload completes*/ };
        $scope.progress = function(percentDone) { /*do something when progress is reported*/ };
        $scope.error = function(file, type, msg) { /*do something if an error occurs*/ };
        $scope.getAdditionalData = function() { /* return additional data to be posted to the server*/ };

    });
这看起来是相关的并且有一些不错的信息,但是您能否解释一下,特别是将它与 bsr 拥有的代码相关联,以及您的代码如何解决他们的问题?
2021-04-24 01:39:10

请看一下我的实现。您可以将以下函数包装到服务中:

function(file, url) {
  var fd = new FormData();

  fd.append('file', file);

  return $http.post(url, fd, {
    transformRequest: angular.identity,
    headers: { 'Content-Type': undefined }
  });
}

请注意,该file参数是一个Blob. 如果你有base64一个文件的版本 - 它可以很容易地更改为Blob

fetch(base64).then(function(response) {
  return response.blob(); 
}).then(console.info).catch(console.error);

您也可以使用 HTML5 上传。你可以使用这个AJAX 上传器

JS代码基本上是:

  $scope.doPhotoUpload = function () {
    // ..
    var myUploader = new uploader(document.getElementById('file_upload_element_id'), options);
    myUploader.send();
    // ..
  }

从 HTML 输入元素读取

<input id="file_upload_element_id" type="file" onchange="angular.element(this).scope().doPhotoUpload()">