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

bsr*_*bsr 42 javascript angularjs

我在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)
Run Code Online (Sandbox Code Playgroud)

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

var payload = {"Name":"abc"};
$http.post('/test', payload)
    .success(function (res) {
    //success
});
Run Code Online (Sandbox Code Playgroud)

Pav*_*esa 130

当必须上传文件并同时发送用户令牌信息时,我遇到了类似的问题.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) {

        });
Run Code Online (Sandbox Code Playgroud)

为了获取文件$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();
            });
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

HTML:

<input type="file" file="file" required />
Run Code Online (Sandbox Code Playgroud)

  • 这很棒!应该是接受的答案. (12认同)
  • 在咬牙切齿之后,我得到了这个(至少在Chrome 48和Angular 1.5.0中使用.Net服务器端和HttpContext.Request.Files).你不必将标题设置为multipart/form-data, XMLHttpRequest为您完成了这项工作.设置它实际上可能会搞砸上传.使用`'Content-Type':undefined`你也不必删除标题.这允许我使用.Net HttpContext.Request.Files API调用来获取文件服务器端 (6认同)
  • 充当魅力.当复制/粘贴工作时我怎么样.男人,节省了大量的时间. (5认同)
  • 我同意这应该是接受的答案,因为它允许您使用自己的API,其中可能需要令牌 (4认同)
  • 在设置之后删除`Content-Type`是为了确保在转换文件时它是form-data然后(在准备好发布post请求之后)这是一个正常的请求`Content-Type:application/json ` (4认同)
  • 这个ALMOST有效... transformRequest:angular.identity就是你所需要的.您已在data参数中设置了数据集.设置标题:{'Content-Type':undefined},你就完成了.Angular负责将边界正确附加到内容类型. (2认同)

Cou*_*ero 19

在发布到Web.Api应用程序时,我无法让Pavel的答案正常工作.

问题似乎是删除标题.

headersGetter();
delete headers['Content-Type'];
Run Code Online (Sandbox Code Playgroud)

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

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

headers: {'Content-Type': undefined}
Run Code Online (Sandbox Code Playgroud)

这是一个完整的例子.

$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;
            }
Run Code Online (Sandbox Code Playgroud)


Jas*_*son 7

我最近写了一个支持本机多文件上传的指令.我创建的解决方案依赖于服务来填补您使用$ http服务识别的差距.我还添加了一个指令,它为角度模块提供了一个简单的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)'/>
Run Code Online (Sandbox Code Playgroud)

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

您可以自行处理Web框架中的文件,但我创建的解决方案提供了将数据提供给服务器的角度接口.您需要编写的角度代码是响应上传事件

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*/ };

    });
Run Code Online (Sandbox Code Playgroud)

  • 这看起来是相关的和一些体面的信息,但你可能会解释一下,特别是它与bsr的代码,以及你如何解决他们的问题? (4认同)