【问题标题】:courrupted jpeg when uploading to parse.com with cordova file transfer plugin使用cordova文件传输插件上传到parse.com时损坏的jpg
【发布时间】:2014-10-09 19:01:53
【问题描述】:

我正在使用 parse.com rest api https://www.parse.com/docs/rest#files 我正在尝试从 Cordova 应用上传照片。我正在使用file pluginfile transfer plugin 的ngCordova 项目wrapper

当我上传照片时,它以某种方式被损坏了。见http://files.parsetfss.com/73b88ac0-8858-4f64-92bf-de6aaf29f525/tfss-7b54f8e8-77fd-4e3d-bbbe-83bf67bb08d0-profile-image.jpeg

如果我将发布请求 Content-Type 更改为 application/json,我们会看到以下 http://files.parsetfss.com/73b88ac0-8858-4f64-92bf-de6aaf29f525/tfss-219ecbb4-091f-45e6-9da1-35ad84022db6-profile-image.jpeg,这相当于上传的 jpeg 的十六进制转储。

--+++++org.apache.cordova.formBoundary
Content-Disposition: form-data; name="file"; filename="no-filename"
Content-Type: image/jpeg
Content-Length: 35476

<binary>
--+++++org.apache.cordova.formBoundary--

将此图像加载到预览中会显示已损坏的警告。在 Photoshop 中它被正确加载,所以信息在那里,只是有一些损坏。

我怀疑cordova 文件传输插件不成熟,默认添加了不需要的参数filefilename。而且没有办法删除它们。见https://github.com/apache/cordova-plugin-file-transfer/blob/master/doc/index.md#upload

如何使用 rest api 和文件传输插件将 jpeg 二进制文件上传到 parse.com?

profilesController.js

// uploads photo to rest api given local file_uri
$scope.addPhoto = function() {

  var options = {};
  options.mimeType = 'image/jpeg';
  options.headers = {
    'X-Parse-Application-Id': 'my-id',
    'X-Parse-REST-API-Key': 'my-key',
    'Content-Type': 'image/jpeg'
  };

  $cordovaFile.uploadFile('https://api.parse.com/1/files/profile-image.jpeg', $scope.imageSrc, options).then(function(result) {
    console.log('result:', result);
    $ionicLoading.hide();
  }, function(err) {
    // An error occured. Show a message to the user
  });
};

【问题讨论】:

    标签: rest cordova parse-platform mime-types content-type


    【解决方案1】:

    我做了 2 项对我有用的更改。

    1.  <preference name="CameraUsesGeolocation" value="false" />
      2.  In camera options 
          saveToPhotoAlbum:true
    

    【讨论】:

      【解决方案2】:

      我花了一段时间才弄清楚这就是我删除多部分标题的方式。

      打开: \platforms\android\src\org\apache\cordova\filetransfer\FileTransfer.java

      寻找:

      sendStream.write(beforeDataBytes);
      totalBytes += beforeDataBytes.length;
      

      注释掉或删除这两行。它们是添加多部分标题的代码。

      【讨论】:

        【解决方案3】:

        目前,文件传输插件发送多格式部分数据,将多部分标头添加到有效负载。也许,服务器不接受多部分标头。尝试从 master 安装文件传输版本,其中指出: '如果存在名为 Content-Type 的标头,则不会使用多部分表单数据。'

        您可以从 master 安装文件传输插件: cordova plugin add https://github.com/apache/cordova-plugin-file-transfer.git

        【讨论】:

        • 我添加了这个标题,图像很好:“Content-Type”:“multipart/form-data”
        【解决方案4】:

        您可以使用 REST api 从 cordova 应用程序上传文件。

        在您的控制器中:

        var cameraOptions = {
            destinationType: 0, // base64
            encodingType: 0 
        };
        
        $scope.takePicture = function() {
            cameraOptions.sourceType = 1;
            navigator.camera.getPicture(onSuccess, onFail, cameraOptions);
        }
        
        $scope.selectPicture = function() {
            cameraOptions.sourceType = 0;
            navigator.camera.getPicture(onSuccess, onFail, cameraOptions);
        }
        
        function onSuccess(picture) {
        
            File.upload(picture)
                .success(function(data) {
                    // upload finish
                });
        
            $scope.$apply(function() {
                $scope.preview = 'data:image/jpeg;base64,' + picture;
            });
        }
        
        function onFail(resp) {
            alert('Error: ' + resp);
        }
        

        在文件服务中:

        angular.factory('File', function ($http) {
            return {
                upload: function (photo) {
        
                    var json = {
                        'base64': photo,
                        '_ContentType': 'image/jpeg'
                    }
        
                    var config = {
                        method: 'POST',
                        url: 'https://api.parse.com/1/files/pict.jpg',
                        data: json,
                        headers: {
                            'X-Parse-Application-Id': 'XXXXX',
                            'X-Parse-REST-API-Key': 'XXXXX'
                        }
                    };
        
                    return $http(config);
                }
            }
        });
        

        【讨论】:

          【解决方案5】:

          答案是插件的 api 与预期的格式不兼容。我求助于使用javascript sdk的文件方法https://www.parse.com/docs/js_guide#files-classes和相机插件的DATA_URL方法https://github.com/apache/cordova-plugin-camera/blob/master/doc/index.md#options

          【讨论】:

            【解决方案6】:

            您能从cordova 请求中转储http 标头吗? IMO 其发送内容类型:mime/multipart 而不是文档指定的内容。一般来说,如果插件只是格式化 REST api 文档中提到的标头,并且文件字节包含在请求正文中的 Http.Entity 中,那么您会没事的。

            自己调用 curl 示例并使用“-v”开关列出标头不是一个坏主意,然后测试您的应用转储 http 标头(如果需要,还可以使用 WIRE)以验证您发送 curl 发送的内容。

            curl -v -X POST  -H "X-Parse-Application-Id: AbR" -H "X-Parse-REST-API-Key: kuI9"  -H "Content-Type: image/*"  --data-binary '@test.png' https://api.parse.com/1/files/test.png
            

            【讨论】:

            • 绝对是api问题。该插件不支持不指定 filefilename 键值对。我现在正在直接使用 File API 和 $http 角度服务并回避插件。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-05-14
            • 1970-01-01
            • 2016-05-12
            • 1970-01-01
            • 1970-01-01
            • 2020-09-27
            • 2014-10-23
            相关资源
            最近更新 更多