├── .env ├── .gitignore ├── README.md ├── package.json ├── public └── client-side.js └── server.js /.env: -------------------------------------------------------------------------------- 1 | CLOUDNAME=yourcloudnamehere 2 | CLOUDAPIKEY=yourapikeyhere 3 | CLOUDINARYSECRET=yourapisecrethere -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | To visit the app in your browser you can use a username of `admin` and a password of `admin`. 2 | 3 | # Important Note 4 | 5 | Please, please, please do **not** accidentally leak your environment variables in your .env file on your Github / GitLab / elsewhere. 6 | 7 | 99.99% of the time you should use .gitignore to exclude your .env file from your repository. 8 | 9 | I only included it in this example because it's super common for people following lessons to include a typo in the variable name for environment variables, and then never be able to figure out why there example is not working. 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple-cloudinary", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "nodemon server.js", 8 | "start": "node server.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "cloudinary": "^1.30.0", 16 | "dotenv": "^16.0.1", 17 | "express": "^4.18.1", 18 | "fs-extra": "^10.1.0", 19 | "nodemon": "^2.0.16" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /public/client-side.js: -------------------------------------------------------------------------------- 1 | const api_key = "your-api-key-here" 2 | const cloud_name = "your-cloud-name-here" 3 | // It's okay for these to be public on client-side JS 4 | // You just don't ever want to leak your API Secret 5 | 6 | document.querySelector("#upload-form").addEventListener("submit", async function (e) { 7 | e.preventDefault() 8 | 9 | // get signature. In reality you could store this in localstorage or some other cache mechanism, it's good for 1 hour 10 | const signatureResponse = await axios.get("/get-signature") 11 | 12 | const data = new FormData() 13 | data.append("file", document.querySelector("#file-field").files[0]) 14 | data.append("api_key", api_key) 15 | data.append("signature", signatureResponse.data.signature) 16 | data.append("timestamp", signatureResponse.data.timestamp) 17 | 18 | const cloudinaryResponse = await axios.post(`https://api.cloudinary.com/v1_1/${cloud_name}/auto/upload`, data, { 19 | headers: { "Content-Type": "multipart/form-data" }, 20 | onUploadProgress: function (e) { 21 | console.log(e.loaded / e.total) 22 | } 23 | }) 24 | console.log(cloudinaryResponse.data) 25 | 26 | // send the image info back to our server 27 | const photoData = { 28 | public_id: cloudinaryResponse.data.public_id, 29 | version: cloudinaryResponse.data.version, 30 | signature: cloudinaryResponse.data.signature 31 | } 32 | 33 | axios.post("/do-something-with-photo", photoData) 34 | }) 35 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config() 2 | const express = require("express") 3 | const cloudinary = require("cloudinary").v2 4 | const fse = require("fs-extra") 5 | const app = express() 6 | app.use(express.static("public")) 7 | app.use(express.json()) 8 | app.use(express.urlencoded({ extended: false })) 9 | 10 | const cloudinaryConfig = cloudinary.config({ 11 | cloud_name: process.env.CLOUDNAME, 12 | api_key: process.env.CLOUDAPIKEY, 13 | api_secret: process.env.CLOUDINARYSECRET, 14 | secure: true 15 | }) 16 | 17 | function passwordProtected(req, res, next) { 18 | res.set("WWW-Authenticate", "Basic realm='Cloudinary Front-end Upload'") 19 | if (req.headers.authorization == "Basic YWRtaW46YWRtaW4=") { 20 | next() 21 | } else { 22 | res.status(401).send("Try again") 23 | } 24 | } 25 | 26 | app.use(passwordProtected) 27 | 28 | app.get("/", (req, res) => { 29 | res.send(` 30 | 31 |
32 | 33 | 34 | 35 |