Angular / PHP:上传$ _POST中的文件数据,而不是$ _FILES

时间:2017-01-25 14:46:22

标签: php angularjs forms post

我在Debian上使用 PHP 5.6.24 上的 AngularJS v1.6.1, Apache 2.4.10 和我&#39 ; m尝试使用$http POST服务将文件上传到我的服务器。 在我的php.ini上,最大文件大小设置为8Mo,最大邮件大小,上传文件打开,内存大小限制设置为128Mo。

形式:

<input type="file" accept="application/pdf" id="uploadOT" max-files="1" ng-model="uploadOT" name="uploadOT" valid-file required ng-class="{'md-input-invalid':uploadForm.uploadOT.$error.validFile}" />

Angular指令:(当输入内容发生变化时,获取FileReader对象并发送文件)

myModule.directive('validFile', function() {
    return {
        require:    'ngModel',
        link:       function(scope, elt, attrs, ctrl) {
            ctrl.$setValidity('validFile', elt.val() !== '');
            elt.bind('change', function() {

                var file = document.getElementById('uploadOT').files;
                var reader = new FileReader();
                reader.onload = function(e) {
                    scope.sendFile(reader, scope.id);
                };
                scope.showUploadProgress = true;
                scope.filename = file[0].name;
                reader.readAsBinaryString(file[0]);

                ctrl.$setValidity('validFile', elt.val() !== '');
                scope.$apply(function() {
                    ctrl.$setViewValue(elt.val());
                    ctrl.$render();
                });
            });
        }
    };
});

内部控制器:

$scope.sendFile = function(reader, id) {
    var fd = new FormData();
    fd.append('id', id);
    fd.append('file', reader.result);
    fd.append('MAX_FILE_SIZE', 8 * 1024 * 1024);
    $http.post('api/upload.php', fd, {
        headers:            {'Content-Type' : undefined },
        transformRequest:   angular.identity
    }).then(function() {
        alert('upload success');
    }, function() {
        $scope.showUploadError = true;
        $scope.showUploadProgress = false;
        $scope.postError = 'Une erreur inconnue est survenue !';
    });
};

在服务器端(文件api/upload.php),我使用$_POST打印变量$_FILESprint_r()

为什么$_FILES始终为空,我的文件数据位于$_POST['file']

我可以使用php函数 $_POST['file'] file_put_contents()数据创建文件,但我无法通过 $_FILES 。它真的很重要(安全问题)吗?

如果我将我的POST Content-Type更改为multipart/form-data,则会发生同样的事情。

3 个答案:

答案 0 :(得分:0)

我认为这是因为你忘了指定表单元素的编码类型。

enctype="multipart/form-data"

因此,通过默认 - 浏览器会假设表单编码类型为&#34; application / x-www-form-urlencoded &#34;以这种方式不支持文件。您仍然可以使用stock编码方法安全地发送文件二进制数据,但这可能是性能和功能决定您选择的因素。我建议运行一些测试来确认哪个是最快的。在某些情况下,差异可以忽略不计,并且可能是为了保持一致。

答案 1 :(得分:0)

跳过FileReader API并直接使用file对象:

<input type=file files-input ng-model="files" ng-change="upload()" />

filesInput指令

angular.module("myApp").directive("filesInput", function() {
  return {
    require: 'ngModel',
    link: function linkFn (scope, elem, attrs, ngModel) {
      elem.on("change", function (e) {
        ngModel.$setViewValue(elem[0].files, "change");
      });
    },
  };
});

upload()功能

 vm.upload = function() {

    //var formData = new $window.FormData();
    //formData.append("file-0", vm.files[0]);

    var config = { headers: { "Content-Type": undefined } };

    $http.post(url, vm.files[0], config)
    .then(function(response) {
      vm.result = "SUCCESS";
    }).catch(function(response) {
      vm.result = "ERROR "+response.status;
    });
  };

XHR API send()方法可以发布file对象或FormData对象。发送file对象更有效率,因为XHR API使用base64 encoding用于具有33%开销的FormData对象。

DEMO on PLNKR.

答案 2 :(得分:0)

为了使其有效,我必须做这些修改:

<强>指令:

myModule.directive('validFile', function() {
    return {
        require:    'ngModel',
        link:       function(scope, elt, attrs, ctrl) {
            ctrl.$setValidity('validFile', elt.val() !== '');
            elt.bind('change', function() {

                var file = document.getElementById('uploadOT').files;
                var reader = new FileReader();
                reader.onload = function(e) {
                    scope.sendFile(file[0], scope.OT);  ////CHANGE HERE
                };
                scope.showUploadProgress = true;
                scope.filename = file[0].name;
                reader.readAsArrayBuffer(file[0]);      ////CHANGE HERE

                ctrl.$setValidity('validFile', elt.val() !== '');
                scope.$apply(function() {
                    ctrl.$setViewValue(elt.val());
                    ctrl.$render();
                });
            });
        }
    };
});

内部控制器

$scope.sendFile = function(file, id) {
        var fd = new FormData();
        fd.append('id', id);
        fd.append('file', file);
        fd.append('MAX_FILE_SIZE', 8 * 1024 * 1024);
        $http({
            method: 'POST',
            url: 'upload.php',
            data: fd,
            headers: {'Content-Type': undefined, 'Process-Data': false},
            transformRequest: angular.identity
        }).then( function() {
            console.log('success');
        }, function() {
            console.log('failure');
        });
    };