【问题标题】:Codename one Upload a picture taken by the camera to amazon s3 bucket代号一 将相机拍摄的照片上传到amazon s3 bucket
【发布时间】:2016-12-17 13:45:16
【问题描述】:

原始问题

我已经按照您的建议进行了尝试,我遇到的问题很少。 以下是我所做的:filePath = Capture.capturePhoto(1024, -1);

我在 MutipartRequest 构造函数中传递 S3_BUCKET_URL 时遇到问题,因此我使用了 rq.setUrl(S3_BUCKET_URL)

我必须添加 rq.setHttpMethod("PUT"); // 因为我收到 405 错误:不支持方法

最后我没有发现任何错误,我确实看到在我创建的存储桶下创建了一个子文件夹。我将网址设置为“https://s3.amazonaws.com/bucket123/test/”我看到创建了测试存储桶,但没有上传图像文件。文件夹大小不是 0,因为它显示了文件的大小,但在该子文件夹中没有找到图像文件。

当我尝试通过 S3 资源管理器访问该文件夹时,我得到了拒绝访问。 1.我使用S3资源管理器手动创建了一个子文件夹并授予了读写权限,但是一旦从代号调用uploadFileToS3方法,我看到权限丢失了。 2. 所以我把acl改成“public-read-write”还是一样的效果。

如果我遗漏了什么,请告知。

谢谢。


修改后的问题 我已经修改了旧问题,并按照 Sahi 的回答进行了修改。

    // Modified the url as following - full path including bucket name and key
    private static final String S3_BUCKET_URL = "https://s3.amazonaws.com/my-bucket/myfile.jpg";

    //String filePath = captured from Camera;
        public void uploadFileToS3(String filePath, String uniqueFileName) {
            MultipartRequest rq = new MultipartRequest();
            rq.setUrl(S3_BUCKET_URL);
            //rq.addArgument("acl", "private");
            //rq.addArgument("key", uniqueFileName);
            rq.addData(uniqueFileName, filePath, "image/jpeg");
            rq.setReadResponseForErrors(true);
            NetworkManager.getInstance().addToQueue(rq);
        }

Now I do see that the file has been uploaded to the bucket as myfile.jpg under my bucket.  The bucket has all the rights since the bucket is given rights to read and write also applied the permissions to sub folders.
Now the myfile.jpg lost all the permissions and I am not able to download that file even though I see it in the bucket.
I accessed it by the url but the file cannot be opened.

I am not sure what I am missing in the header or request. I am really trying to get this working but not getting where I wanted to.  This is very important piece for the app I am working on.  

Please provide any feedback.

Thank you.

--------------------------------------------------------------------------

添加代码

私有静态最终字符串 S3_BUCKET_URL = "https://s3.amazonaws.com/my-bucket/";

当我拥有上述 url 时,my-bucket 被创建为未知对象(没有文件夹图标),但我确实看到文件大小是实际图像大小。

//String filePath = captured from Camera;
public void uploadFileToS3(String filePath, String uniqueFileName) {
//uniqueFileName including sub folder - subfolder/my-image.jpg
MultipartRequest rq = new MultipartRequest();
rq.setUrl(S3_BUCKET_URL);
rq.addArgument("acl", "public-read-write");
rq.addArgument("key", uniqueFileName);
rq.addData(uniqueFileName, filePath, "image/jpeg");
rq.setReadResponseForErrors(true);
NetworkManager.getInstance().addToQueue(rq);
}

看起来我没有正确上传对象。我确实浏览了亚马逊文档,但找不到与通过 http 上传相关的任何内容。我真的被困住了,我希望能解决这个问题。您是否有任何可以简单地上传到 s3 的工作代码?


More details: I am adding more detail to the question as I am still not able to resolve this.

    // Original S3_BUCKET_URL 
    String S3_BUCKET_URL = "https://s3.amazonaws.com/my-bucket/";
    // With this url I am getting 400 : Bad Request Error
    // I added the uniqueFilename (key) to the url as 
    String uniqueFilename = "imageBucket/image12345.jpg";
    String S3_BUCKET_URL = "https://s3.amazonaws.com/my-bucket   /"+uniqueFilename;
    //Now I do see the file I believe it's the file, the 
    //subfolder inherits the rights from bucket (read, write). 
    //Not the image file.
    //When I click on the file using s3 client browser I got message
    //prompted Access Denied.

    // my function to call s3 bucket
    public void takePicture()
    {
        String stringImg = Capture.capturePhoto(1024, -1);    
        MultipartRequest rq = new MultipartRequest();
        rq.setUrl(S3_BUCKET_URL);
        rq.addArgument("key", uniqueFilename );
        rq.addArgument("acl", "public-read-write");
        rq.setHttpMethod("PUT"); // If I don't specify this I am getting 
                                 // 405 : Method Not Allowed Error.
        rq.addData("file", stringImg, "image/jpeg"); 
        //Captured Image from camera
        rq.setFilename("file", uniqueFilename);
        NetworkManager.getInstance().addToQueue();
    }

在这一点上,我相信我已经完成了所有建议的方式,但我仍然遇到同样的错误。我相信我没有做错任何事,我不想相信我是唯一一个试图这样做的人:)

我真的需要你的帮助来解决这个问题,以保持这个项目。我想知道是否有任何 Amazon s3 sdk 或库可以在代号一中使用。

请查看此内容并让我知道这是否真的可以通过代号一来实现。

谢谢。

【问题讨论】:

  • 另外,当我的网址为 S3_BUCKET_URL = "s3.amazonaws.com/my-bucket/";我收到 400 错误:错误请求

标签: amazon-web-services amazon-s3 codenameone


【解决方案1】:

我已经测试了这段代码,它应该可以工作,但是它取决于对 Codename One 的修复来处理 Amazon API 的一些愚蠢行为:

Form hi = new Form("Upload");

Button upload = new Button("Upload");
hi.add(upload);
upload.addActionListener(e -> {
    String file = Capture.capturePhoto();
    if(file != null) {
        try {
            String uniqueFileName = "Image" + System.currentTimeMillis() + ".jpg";
            MultipartRequest rq = new MultipartRequest();
            rq.setUrl("https://s3.amazonaws.com/my-bucket/");
            rq.addArgument("key", uniqueFileName);
            rq.addArgument("acl", "private");
            rq.addData("file", file, "image/jpeg");
            rq.setReadResponseForErrors(true);
            NetworkManager.getInstance().addToQueueAndWait(rq);            
            if(rq.getResponseCode() != 200 && rq.getResponseCode() != 204) {
                System.out.println("Error response: " + new String(rq.getResponseData()));
            }
            ToastBar.showMessage("Upload completed", FontImage.MATERIAL_INFO);
        } catch(IOException err) {
            Log.e(err);
        }
    }
});

hi.show();

运行下面的代码时(带有帖子),我没有收到您描述的错误,而是收到来自 Amazon 的错误,表明密钥的顺序不正确。显然,亚马逊依赖于提交字段的顺序,这非常愚蠢。不幸的是,当您添加参数时,我们会忽略该顺序,并且由于这是一个发布请求,因此解决此问题的代码并非易事。

我已对 Codename One 进行了修复,它将尊重添加参数的自然顺序,但由于我们已在本周发布,因此只会在下周五(2016 年 12 月 23 日)发布。因此,在更新之后,上面的代码应该可以按预期工作。

旧答案供参考

我尚未对此进行测试,但应该可以使用类似的方法:

private static final String S3_BUCKET_URL = "https://s3.amazonaws.com/my-bucket/";


public void uploadFileToS3(String filePath, String uniqueFileName) {
    MultipartRequest rq = new MultipartRequest(S3_BUCKET_URL);
    rq.addArgument("acl", "private");
    rq.addArgument("key", uniqueFileName);
    rq.addData("file", filePath, "image/jpeg");
    rq.setFilename("file", uniqueFileName);
    rq.setReadResponseForErrors(true);
    NetworkManager.getInstance().addToQueue(rq);
}

请注意,这不会进行授权,因此它假定存储桶至少可用于写入。

【讨论】:

  • 我猜你遇到了这个问题,因为我在那里有 acl/private 选项。尝试尝试其他值。在我们的例子中,我们需要非常有限的只写访问权限,并且读取是针对非常特定的用户的。
  • 嗨,Shai,感谢您的快速响应。我将按照您的指示提出问题和更新 cmets。我确实像上面提到的那样尝试了 rq.addArgument("acl", "public-read-write") ,但仍然没有运气。我会进一步调查,如果您遇到任何问题,请告知。谢谢。
  • HI Shai,我已经用我的发现编辑了这个问题。请查看。
  • 请注意,当您编辑问题时,最好保留原始问题并在下面添加详细信息。否则到达问题的人将无法理解答案。请注意,我的 S3 URL 末尾不包含文件名,因为文件名在提交(键)中。
  • 嗨,Shai,我已经按照您的建议包含了原始问题。一开始我确实在密钥中有文件名。但是一旦文件上传,我并没有真正看到文件名。我将acl更改为“public-read-write”。当我尝试下载该文件时仍然提示访问被拒绝。我会将我的代码添加到原始问题并在每一行上进行评论。
【解决方案2】:
  1. 在您的服务器上生成预签名 URL:

  2. 将 URL 传递给移动客户端。

    IAmazonS3 client;
    client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1);
    // Generate a pre-signed URL.
    GetPreSignedUrlRequest request = new GetPreSignedUrlRequest
        {
           BucketName = bucketName,
            Key        = objectKey,
            Verb       = HttpVerb.PUT,
            Expires    = DateTime.Now.AddMinutes(5)
        };
    string url = null;
    url = s3Client.GetPreSignedURL(request);
    
  3. 移动客户端可以使用旧的纯 PUT HTTP 请求将文件上传到该 URL:

    // Upload a file using the pre-signed URL.
    HttpWebRequest httpRequest = WebRequest.Create(url) as HttpWebRequest;
    httpRequest.Method = "PUT";
    using (Stream dataStream = httpRequest.GetRequestStream())
    {
       // Upload object.
    }
    
    HttpWebResponse response = httpRequest.GetResponse() as HttpWebResponse;
    

您可以在http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjectPreSignedURLDotNetSDK.html查看官方文档

【讨论】:

  • 谢谢 Sergey,我实际上是在尝试在基于 Java 的框架 Codename One 上实现这一点。希望得到支持。再次感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-03
  • 1970-01-01
相关资源
最近更新 更多