Reputation: 569
react-native + expo
TL;DR: Does anyone have a working example of react-native/expo working with an in app camera and uploading an image to the 'new' google api?
Why I think (5) seems like it is working, because the getUploadToken function returns successfully, response 200, and provides a key.
Why I think it might be a dumb service on the other end of (5), I can post just about anything to it and it will return successfully.
My hunch is that there is something wrong with the way I am uploading the image to the /uploads endpoint.
IE: not in the correct format.
this.state.image == {'base64':'base64string','uri':'file://...',...}
I do see an album is being created within my google photos, and I can see that it is set to shareable, with no privileges (users can not comment, or add their own photos)
2 MAKE ALBUM
makeAlbum = () => {
//MAKE ALBUM
fetch('https://photoslibrary.googleapis.com/v1/albums', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+this.state.accessToken
},
body: JSON.stringify({
"album": {"title": this.state.albumTemp}
}),
}).then((response) => response.json())
.then((response) => {
[
this.shareAlbum(response),
console.log('make: ',response)
]
});
}
}
3 MAKE ALBUM SHAREABLE
shareAlbum = (response) =>{
this.setState({albumId:response.id})
//MAKE ALBUM SHAREABLE
fetch('https://photoslibrary.googleapis.com/v1/albums/'+this.state.albumId+':share',{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+this.state.accessToken
}
}).then((response) => response.json())
.then((response)=>{
[
this.setState({shareable:response.shareInfo.shareableUrl}),
console.log('share1: ',this.state.shareable),
console.log('share2: ',response),
]
});
}
4 CAPTURE PHOTO
capturePhoto = async () => {
let image = await this._camera.takePictureAsync({
base64: true,
quality: .5,
width: 1920,
fixOrientation: true
})
this.setState({ image: image, capturing: false })
// delay the capture a few seconds to make sure it's rendered
setTimeout(async () => {
let result = await takeSnapshotAsync(this._previewRef, {
format: 'png',
result: 'tmpfile',
quality: 1
});
//upload the photo to google photos album
this.getUploadToken(image)
}, 1000)
}
5 GET UPLOAD TOKEN
getUploadToken = (image) => {
let name = this.state.image.uri.split('/')
name=name[name.length-1]
fetch('https://photoslibrary.googleapis.com/v1/uploads', {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'Authorization': 'Bearer '+this.state.accessToken,
'X-Goog-Upload-File-Name': name,
'X-Goog-Upload-Protocol': 'raw'
},
body:image,
})
.then((response) => {
console.log('setup upload: ',response)
this.uploadPhoto(response._bodyText);
})
}
6 UPLOAD PHOTO
uploadPhoto = (token) => {
fetch('https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+this.state.accessToken,
},
body:JSON.stringify({
"albumId": this.state.albumId,
"newMediaItems": [
{
"description": "Event Photo",
"simpleMediaItem": {
"uploadToken": token
}
}
]
})
})
.then((response) => {
console.log('actual upload: ',response)
this.setState({ ready: true, image: null })
})
}
Upvotes: 2
Views: 3413
Reputation: 1808
5 GET UPLOAD TOKEN API works find, just the description is wrong on Google Documentation. Instead of Base64 the input is in form of Binary. I have tried in Postman(below screenshot):
Get Upload Token API: Get Upload Token API
Upload Media: enter image description here
Upvotes: 3
Reputation: 15711
Step 5 certainly does not work... You are not sending an image at all!
In step 4 you call this:
this.getUploadToken()
While in step 5
getUploadToken = (image) => {
image is then used as body.
Did you check your network tab while testing? It looks like you would be receiving a 400 error.
Upvotes: 1
Reputation: 21
I've been trying the same thing in a Node Express app.
Don't forget that you need to upload the image in binary, and not in base64.
It also looks like you don't pass a parameter in step 4 to the function getUploadToken().
My app also returns the "message": "NOT_IMAGE: There was an error while trying to create this media item."
.
In my node app i convert the Buffer to a binary with
const fileBinary = file.data.toString('binary')
Upvotes: 1