2016-04-29 134 views
3

我正在研究React Native應用程序,我正在嘗試從用戶相機膠捲中提取圖像,將它們轉換爲base64字符串並將它們存儲到Amazon S3以備將來使用。將base64字符串保存到Amazon S3

跟蹤此博客文章中,我能夠利用用戶的相機膠捲和圖像轉換爲Base64: react-native-creating-a-custom-module-to-upload-camera-roll-images

我那麼的base64字符串圖像數據發送到我已經建立了一個簡單的Express服務器將數據發佈到我的Amazon S3存儲桶。

// Only getting first img in camera roll for testing purposes 
CameraRoll.getPhotos({first: 1}).then((data) => { 

    for (let i = 0; i < data.edges.length; i++) { 
    NativeModules.ReadImageData.readImage(data.edges[i].node.image.uri, (imageBase64) => { 

     // Does the string have to be encoded? 
     // const encodeBase64data = encodeURIComponent(imageBase64); 

     const obj = { 
     method: 'POST', 
     headers: { 
      'Accept': 'application/json', 
      'Content-Type': 'application/json', 
     }, 
     body: JSON.stringify({ 
      'img': imageBase64 
     }) 
     } 

     fetch('http://localhost:3000/saveImg', obj) 
     .then((res) => { 
      console.log(JSON.parse(res._bodyInit)); 
     }) 

    }) 
    } 

imageBase64在這個實例變量是一個相當大的字符串讀,如:/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAATU0AKgAAA...abX+Yub/API3zf8A7G2Z/wDqdiD/AExyf/kT5R/2Kst/9QqB0x6H6GuBbr1R6D2foz+ZT/gof/yep8bf934f/wDqC6PX96+Cn/JruFf+6z/6t8UfwP4wf8nM4n9Mq/8AVbRPjOv1I/OAoA//2Q== 隨着...是幾個字符。

我送這個的base64字符串到我的Express服務器和發佈數據:

app.post('/saveImg', function(req, res) { 

    // this will be moved once testing is complete 
    var s3Bucket = new AWS.S3({ params: {Bucket: '[my_bucket_name]'} }); 

    // Do I need to append this string to the image? 
    var baseImg = 'data:image/png;base64,' + req.body.img; 

    var data = { 
    Key: test_img, 
    Body: req.body.img, 
    ContentEncoding: 'base64', 
    ContentType: 'image/png' 
    }; 

    s3Bucket.putObject(data, function(err, data){ 
    if (err) { 
    console.log(err); 
    console.log('Error uploading data: ', data); 
    } else { 
    res.send(data); 
    console.log('successfully uploaded the image!'); 
    } 
}); 
    // res.send(base64data) 
}); 

我成功地將數據發送到Amazon S3,看看我的圖像文件中的桶然而,當我嘗試訪問鏈接來查看實際圖片本身,或將其拉入我的React Native應用程序,我什麼也沒得到。

即如果我訪問的URL,上面它在亞馬遜S3後,我得到:

https://s3.amazonaws.com/my_bucket_name/test_img 
This XML file does not appear to have any style information associated with it. The document tree is shown below. 
<Error> 
    <Code>AccessDenied</Code> 
    <Message>Access Denied</Message> 
    <RequestId>BCE6E07705CF61B0</RequestId> 
    <HostId> 
aF2l+ucPPHRog1QaaXjEahZePF0A9ixKR0OTzlogWFHYXHUMUeOf2uP7D/wtn7hu3bLWG8ulKO0= 

    </HostId> 
</Error> 

我手動上傳圖片到這個相同的桶和他們的鏈接出現罰款,我還能夠將它們拖入我的React Native應用程序中,無需查看任何問題。

我的問題是我得到base64字符串數據並將其發送到我的Express服務器以保存到我的存儲桶之間做錯了什麼? base64字符串是否必須進行編碼? 在發送到Express之前,是否需要將base64字符串轉換爲Blob?

感謝您的幫助!

+0

訂閱,我也需要這個 –

回答

1

這是一個許可的事情,並且與ReactNative和Base64-enconding無關。

你有一個「存取遭拒」 - 錯誤,這意味着該圖像是不公開的。只有當你使用正確的權限(或者甚至是特定的文件,我會在下面解釋)配置你的存儲桶時,你將會收到一個圖像的內容,而不需要簽名。

要調查這是否是您可以嘗試在s3控制檯中公開圖像的根本原因。只要到your s3-bucket和對一個圖像文件中的鼠標右鍵點擊:

enter image description here

在上下文菜單是爲你列出了兩個有趣的項目:「張揚」「打開「

如果您選擇「打開」,您將獲得該文件的「簽名url」,這意味着該圖片的普通url將被添加特定參數以使該文件公開一段時間:

enter image description here

也可以嘗試一下「公開」,並再次刷新圖像的URL,看它是否可現在你。

1.方法,鬥寬:

一種解決方案是創建一個IAM-政策爲整個鬥,使公衆在它的每一個對象:

{ 
    "Version": "2008-10-17", 
    "Statement": [{ 
    "Sid": "AllowPublicRead", 
    "Effect": "Allow", 
    "Principal": { 
     "AWS": "*" 
    }, 
    "Action": [ "s3:GetObject" ], 
    "Resource": [ "arn:aws:s3:::YOUR_BUCKET_NAME/*" ] 
    }] 
} 

所以去你的AWS控制檯中的存儲桶,單擊存儲桶,然後在右側窗格中打開「權限」。您可以創建一個像上面那樣的新策略。

enter image description here

2.第二解決方案,特定對象

另一種方法是添加ACL-specific headers到putObject法:

'ACL'   => 'public-read' 

我不知道你的後臺-sdk,但我猜是這樣的:

var data = { 
    Key: test_img, 
    Body: req.body.img, 
    ContentEncoding: 'base64', 
    ContentType: 'image/png', 
    ACL: 'public-read', 
    }; 

我剛剛在這裏添加了ACL特定的行。 根據SDK的不同,可能需要使用普通的aws-headers「x-amz-acl:public-read」而不是「ACL:public-read」。試試兩個。

+0

不幸的是,這個解決方案並沒有爲我工作。我在IAM策略中爲我的存儲桶添加了內容,當我嘗試從相應的url上加載從相機膠捲保存的圖像時,我只看到頁面左上角出現一個空白的白色正方形。我確定我桶中的圖像也是公開的,而且我仍然遇到同樣的問題。這只是我從我的相機中加載的圖像,作爲base64字符串,並不像我手動上傳的那樣工作,因爲測試顯示正常。 – Onaracs

0

將存儲桶策略添加到您的存儲桶可以解決問題。

2

我剛碰到同樣的問題。在上傳到S3之前,您必須將base64字符串轉換爲Blob。

This answer解釋如何做到這一點的轉換。使用node-fetch,下面介紹如何在你的榜樣整合:

require('node-fetch') 

app.post('/saveImg', function(req, res) { 

    // this will be moved once testing is complete 
    var s3Bucket = new AWS.S3({ params: {Bucket: '[my_bucket_name]'} }); 

    var imageUri = 'data:image/png;base64,' + req.body.img; 

    fetch(imageUri) 
    .then(function(res){ return res.blob() }) 
    .then(function(image){ 
     var data = { 
     Key: test_img, 
     Body: image, 
     ContentEncoding: 'base64', 
     ContentType: 'image/png' 
     }; 

     s3Bucket.putObject(data, function(err, data){ 
     if (err) { 
     console.log(err); 
     console.log('Error uploading data: ', data); 
     } else { 
     res.send(data); 
     console.log('successfully uploaded the image!'); 
     } 
    }); 
    }) 
}); 

一旦這樣做了,你便可以預覽上傳的圖片上S3或者拉入你的應用程序。