Codename one将相机拍摄的照片上传到亚马逊s3水桶

时间:2016-12-12 05:19:43

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

原始问题

我按照你的建议尝试过,我遇到的问题很少。 以下是我做的: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方法看到权限丢失,就给予了读写权限。 所以我确实将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.

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

添加代码

private static final String 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();
    }

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

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

请查看此内容并告诉我这是否真的可以通过代号实现。

谢谢。

2 个答案:

答案 0 :(得分:0)

  1. 在您的服务器上生成预签名的网址:

  2. 将thar 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;
    
  4. 您可以查看http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjectPreSignedURLDotNetSDK.html

    上的官方文档

答案 1 :(得分:0)

我已经测试了这段代码,它应该可以工作但是它依赖于修复Codename One来处理亚马逊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();

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

我已经修复了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);
}

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