【问题标题】:Meteor Slingshot Cordova/Android "error : failed to upload file to cloud storage [-0]"Meteor Slingshot Cordova/Android“错误:无法将文件上传到云存储 [-0]”
【发布时间】:2016-12-23 10:28:02
【问题描述】:

我有一个工作流星/科尔多瓦应用程序,它使用弹弓上传到 AWS/S3。我可以从浏览器和 iOS 上传和查看应用内照片。

但是,在 Android 上,我无法从 slingshot 提供的 AWS 链接加载照片并存储在我的数据库中,当我尝试上传照片时,我收到一条错误消息:

    "error : failed to upload file to cloud storage [-0]"

是否有什么我遗漏的/我应该为 android 配置 slingshot/我的应用程序的特定于 android 的东西?任何帮助将不胜感激。谢谢!

相关的客户端代码(减去文件限制):

//upload to AWS once file is selected
'change #imgUpload' : function(){
  var uploader = new Slingshot.Upload("uploadFiles");
  var questionId = Session.get('selectedQuestion');
  uploader.send(document.getElementById('uploadInput').files[0], function (error, downloadUrl) {
    if (error) {
      // Log service detailed response
      console.log(error)
      console.error('Error uploading' );
      alert (error);
    }
    else {
      Meteor.call('uploadImage', questionId, downloadUrl);
    }
  });

相关的服务器端方法:

  'uploadImage' : function(questionId, downloadUrl){
check(questionId, String);
check(downloadUrl, String);
questionsList.update({_id: questionId},
                      {$set: {
                        picUrl: downloadUrl
                      }
                    });
}, //end upload image

相关的服务器端指令(减去文件限制):

Slingshot.createDirective("uploadFiles", Slingshot.S3Storage, {
  bucket: <bucketname>,
  acl: "public-read",


  authorize: function(){
    //you can't upload if youre not logged in
    if(!this.userId){
      var message = "Please log in before posting files";
      throw new Meteor.Error("Login Required", message);
    }
    return true;
  },

  key: function(file){
    //store file in a directory based on a users team name
    var teamName = Meteor.user().roles.defaultGroup[0]
    return teamName + "/" + file.name;
  }
});

相关的mobile_config.js访问规则:

App.accessRule('https://<app-name>.herokuapp.com/*');
App.accessRule('http://<app-name>.herokuapp.com/*');
App.accessRule('https://s3.amazonaws.com/<bucketname>/*');
App.accessRule('http://localhost:3010/*');

显示图片的相关模板:

  {{#if theQuestion.picUrl}}
        <img src="{{theQuestion.picUrl}}" width="300px" height="300px"  class="userPic">
  {{/if}}

上传图片的相关模板:

<template name="uploader">
  <form id="imgUpload">
    <input id='uploadInput' class="fileLoader" name="file" type="file">
    <label for="file" class="uploadWords">Tap here to upload/take a  picture</label>
  </form>

文件限制:

    Slingshot.fileRestrictions("uploadFiles", {
  allowedFileTypes: ["image/png", "image/jpeg", "image/gif"],
  maxSize: 10 * 1024 * 1024 // 10 MB (use null for unlimited)
});

【问题讨论】:

  • 您是否对每个设备使用相同的文件?它是什么类型的文件?
  • 我是,jpeg和png都有,都不显示,android上传的都是jpeg
  • 我们可以看到Slingshot服务器方法的文件限制代码吗?另外,您是否尝试过从上传的文件创建 Blob,然后将 Blob 发送到 Slingshot?如果这适用于 iOS 和浏览器,这似乎很愚蠢,但值得一试,看看是否有任何变化。让我知道您是否需要一个快速代码 sn-p。我在使用 Slingshot 做几乎相同的事情,但还没有在 Android 上使用它。
  • 这只是 slingshot 文档中的样板限制,不过我已将其添加到问题中。接下来我会尝试上传一个 blob 并让你知道它的进展情况(这不是我唯一的项目,所以可能需要一秒钟),感谢你的帮助/输入!

标签: android cordova meteor amazon-s3 meteor-slingshot


【解决方案1】:

如果其他人遇到此问题,以供将来参考,我最终撕掉了流星弹弓并使用 https://github.com/Lepozepo/S3 。效果很好。

如有任何代码,请随时给我发消息,但我基本上使用了示例中提供的样板代码。

【讨论】:

    【解决方案2】:

    遇到了同样的问题,我发现是这样的。 我们使用 Webkit 创建的文件对象与 Andriod 上可用的文件对象不同。 Webkit 上的 File Object 构造函数是

    new File([Blob],"FileName.png",{type: "image/png"});
    

    与 Cordova 不同的是,在使用“uploader.send”而不是传递文件对象(由 Meteor/Cordova 内部创建)时解决问题,直接传递 Blob 对象,我用来创建的代码blob 对象是

    b64toBlob = function(b64Data, contentType, sliceSize) {
    contentType = contentType || '';
    sliceSize = sliceSize || 512;
    
    var byteCharacters = atob(b64Data.split(',')[1]);
    var byteArrays = [];
    
    for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        var slice = byteCharacters.slice(offset, offset + sliceSize);
    
        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }
    
        var byteArray = new Uint8Array(byteNumbers);
    
        byteArrays.push(byteArray);
    }
    
    var blob = new Blob(byteArrays, {type: contentType});
    return blob;}
    

    而我最终通过的方式构造我的代码是

        if (Meteor.isCordova) {
        console.log("Detected Mobile device");
        var blobFile = b64toBlob(data, "image/png");
        blobFile.name = "userPhoto.png";
        newFile = blobFile;
    } else {
        newFile = new File([b64toBlob(data, "image/png")], "usePhoto.png", {type: "image/png"});
    }
    uploader.send(newFile, function (error, downloadUrl) {
    //Deal with the download URL
    }
    

    【讨论】:

    • 我认为这可能是因为 Cordova 的文件插件 (cordova-plugin-file) 覆盖了几个本机对象,包括标准文件对象。我通过在初始化 cordova-plugin-file 之前捕获原始 F​​ile 对象达到了相同的解决方案。
    猜你喜欢
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    相关资源
    最近更新 更多