错误500和CORS:$ http和$ window.XMLHttpRequest

时间:2016-02-24 13:57:37

标签: angularjs http file-upload xmlhttprequest cors

在我的一个angularJS项目中,我决定使用ng-droplet,这允许我创建拖放区域以通过我的api在服务器上上传图像。

设置插件后,我试了一下,但是我得到了:

XMLHttpRequest cannot load http://myapi.com/api/items. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8383' is therefore not allowed access. The response had HTTP status code 500.

Access-Control-Allow-Origin设置为" *"在服务器端,我在其他api端点上做请求没有问题。

所以我试着看看插件是如何创建请求并发送的,这里是如何:

$scope.uploadFiles = function uploadFiles() {

                // Reset...
                $scope.isError = false;

                var httpRequest   = new $window.XMLHttpRequest(),
                    formData      = new $window.FormData(),
                    queuedFiles   = $scope.filterFiles($scope.FILE_TYPES.VALID),
                    fileProperty  = $scope.options.useArray ? 'file[]' : 'file',
                    requestLength = $scope.getRequestLength(queuedFiles),
                    deferred      = $q.defer();

                // Initiate the HTTP request.
                httpRequest.open('post', $scope.options.requestUrl, true);

                /**
                 * @method appendCustomData
                 * @return {void}
                 */
                (function appendCustomData() {

                    if (!$scope.options.disableXFileSize) {

                        // Setup the file size of the request.
                        httpRequest.setRequestHeader('X-File-Size', requestLength);

                    }

                    // ...And any other additional HTTP request headers, and POST data.
                    $scope.addRequestHeaders(httpRequest);
                    $scope.addPostData(formData);

                })();

                /**
                 * @method attachEventListeners
                 * @return {void}
                 */
                (function attachEventListeners() {

                    // Define the files property so that each listener has the same interface.
                    $scope.listeners.files       = queuedFiles;
                    $scope.listeners.deferred    = deferred;
                    $scope.listeners.httpRequest = httpRequest;

                    // Configure the event listeners for the impending request.
                    $scope.listeners.progress();
                    $scope.listeners.success();
                    $scope.listeners.error();

                })();

                // Iterate all of the valid files to append them to the previously created
                // `formData` object.
                $angular.forEach(queuedFiles, function forEach(model) {
                    formData.append(fileProperty, model.file);
                });

                // Voila...
                $scope.isUploading = true;

                httpRequest.send(formData);
                return deferred.promise;

            };

正如你所看到的,他没有使用$ http而是$ window.XMLHttpRequest。

所以我尝试在同一个端点(http://myapi.com/api/items)的测试控制器上进行文件上传,但这次使用$ http。

像这样:

        var fileInput = document.getElementById('uploadedFile');
    var file = fileInput.files[0];
    var formData = new FormData();
    formData.append('title', "rfsdfsd");
    formData.append('description', "rfsdfhgfhfgsd");
    formData.append('category', 1);
    formData.append('price', 20);
    formData.append('file', file);



    $http.post('http://myapi.com/api/items', formData, {

        headers: {
            'Content-Type': undefined
        }
    });

请注意' Content-Type&#39 ;: undefined ,因为当我尝试这个时,它有效!文件实际上传,我得到200响应代码。

如果我将Content-Type从未定义更改为" multipart / form-data"或其他任何内容,或者如果我删除该行,我从上面得到错误并上传失败。

在角度文档中,据说将Content-Type设置为" undefined"明确删除标题:

  

要基于每个请求显式删除通过$ httpProvider.defaults.headers自动添加的标头,请使用headers属性,将所需标头设置为undefined。

似乎删除Content-Type标头的事实是它与$ http一起使用的部分原因。

所以我也尝试在这个测试控制器中使用$ window.XMLHttpRequest:

                var httpRequest = new $window.XMLHttpRequest();

    var fileInput = document.getElementById('uploadedFile');
    var file = fileInput.files[0];
    var formData = new FormData();
    formData.append('title', "rfsdfsd");
    formData.append('description', "rfsdfhgfhfgsd");
    formData.append('category', 1);
    formData.append('price', 20);
    formData.append('file', file);

    httpRequest.open('post', 'http://myapi.com/api/items', true);
    httpRequest.send(formData);

但是这个给了我和以前一样的CORS错误。我还尝试手动添加Content-Type标头,如下所示:

httpRequest.setRequestHeader('Content-Type', undefined);

httpRequest.setRequestHeader('Content-Type', null);

或""," "等等,但似乎没有任何作用,我总是得到:

POST http://myapi.com/api/items 400 (Bad Content-Type header value: 'undefined')

那么,为什么它可以使用$ http和Content-Type设置为undefined,如何修改ng-droplet使其工作? (我不想用$ http而不是$ window.XMTHttpRequest重写整个事情。)

为什么在使用$ window.XMTHttpRequest或没有Content-Type标头的$ http或者Content-Type设置为未定义的任何内容时会出现此错误?

Ps :如果有人问:ng-droplet提供了自己的方式来添加POST数据,这是我使用的端点所需要的。像这样:

$scope.interface.setPostData({title: "test", description: 'testetstsetest', price: 20, category: 1});

所以它不是问题来源。

编辑:

我解决了它,我忘了我有一个Http拦截器,它自动为所有$ http请求添加一个Authorization标头。我不知道的事情是它没有添加到$ window.XMLHTTPRequest。所以我手动添加它,现在它可以工作。

0 个答案:

没有答案