I need to secure client side upload to cloudinary,
So that I generated a signature token from my node server side using cloudinary api_secret key and time,
used this code
api_sign_request = function(params_to_sign, api_secret)
. After these how to upload the image to cloudinary from front end side using this token
3 Answers
Let's all take a moment to point out how horrible Cloudinary's documentation is. It's easily the worst i've ever seen. Nightmare fuel.
Now that i've got that off my chest... I really needed to be able to do this and I spent way too long banging my head against walls for what should be extremely simple. Here it is...
Server (Node.js)
You'll need an endpoint that returns a signature-timestamp pair to the frontend:
import cloudinary from 'cloudinary'
export async function createImageUpload() {
const timestamp = new Date().getTime()
const signature = await cloudinary.utils.api_sign_request(
{
timestamp,
},
process.env.CLOUDINARY_SECRET
)
return { timestamp, signature }
}
Client (Browser)
The client makes a request to the server for a signature-timestamp pair and then uses that to upload a file. The file used in the example should come from an <input type='file'/>
change event etc.
const CLOUD_NAME = process.env.CLOUDINARY_CLOUD_NAME
const API_KEY = process.env.CLOUDINARY_API_KEY
async function uploadImage(file) {
const { signature, timestamp } = await api.post('/image-upload')
const form = new FormData()
form.append('file', file)
const res = await fetch(
`https://api.cloudinary.com/v1_1/${CLOUD_NAME}/image/upload?api_key=${API_KEY}×tamp=${timestamp}&signature=${signature}`,
{
method: 'POST',
body: form,
}
)
const data = await res.json()
return data.secure_url
}
That's it. That's all it takes. If only Cloudinary had this in their docs.
Many thanks to @jpschroeder's answer, which pointed me in the right direction from the start.
As far as I know there is currently (Jan, 2020) no documented way to generate secure signed URLs for uploading files like you would with S3. That's not to say it can't be done because the documentation hints that there is a way to do it, but I can't seem to find where to explains it.
This means you can only use Cloudinary’s "unsigned" uploads API, which seems borderline abandoned at this point since the only front end upload SDK they have is only for jQuery. Yeah...jQuery – if you've never heard of it don't be embarrassed, us old timers used to use it back in the old days while we listened to nirvana on cassette tape.
They do have 1 broken example on CodePen of doing an unsigned upload from the browser via vanilla JS. My personal axios/ES2015 example is this:
import axios from 'axios'
const cloudName = 'foofoo'
const unsignedUploadPrefix = 'foobar'
const url = `https://api.cloudinary.com/v1_1/${cloudName}/upload`
document.getElementById('fileinput').addEventListener('change', (e) => {
const data = new FormData()
const file = e.target.files[0]
data.append('upload_preset', unsignedUploadPrefix)
data.append('file', file)
axios.post(url, data)
})
Using our upload widget is a good way to go if you want to have client-side uploading.
What you could also try is to have unsigned uploads using the browser, which we also support.
Although they are less secure than signed uploads, they require to configure an upload preset which can be done only from your end and can be changed immediately to prevent abuse.