I am using cloudinary to upload photos on my webpage. I have added a new function to the webpage ( facebook login) and now the cloudinary throw an error when I try to upload a photo like before.
"/home/ubuntu/workspace/YelpCamp/node_modules/cloudinary/lib/utils.js:982 throw "Must supply api_key"; ^ Must supply api_key"
The API_KEY, API_SECRET and the CLOUD_NAME are saved in a .env file, and these are correct.
var express = require("express"); var router = express.Router(); var Campground = require("../models/campground"); var middleware = require('../middleware') ; //because of the index.js default name var geocoder = require('geocoder'); /////////////////////////////////////// // MULTER var multer = require('multer'); var storage = multer.diskStorage({ filename: function(req, file, callback) { callback(null, Date.now() + file.originalname); } }); var imageFilter = function (req, file, cb) { // accept image files only if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/i)) { return cb(new Error('Only image files are allowed!'), false); } cb(null, true); }; var upload = multer({ storage: storage, fileFilter: imageFilter}); /////////////////////////////////////// //CLOUDINARY var cloudinary = require('cloudinary'); cloudinary.config({ cloud_name: process.env.CLOUD_NAME, api_key: process.env.CLOUD_KEY, api_secret: process.env.CLOUD_SECRET }); router.post('/', middleware.isLoggedIn, upload.single('image'), function(req, res) { console.log(req.user); //GEOCODER geocoder.geocode(req.body.location, function (err, data) { //CLOUDINARY UPLOAD cloudinary.uploader.upload(req.file.path, function(result) { var image = { path: result.secure_url, id: result.public_id }; var name = req.body.name; var price = req.body.price; var description = req.body.description; if(req.user.facebook.username) { var username = req.user.facebook.username; } else { username = req.user.local.username; } var author = { id: req.user._id, username: username }; if(!data.results[0]) { var lat = 90; var lng = 0; var location = "North Pole"; } else { lat = data.results[0].geometry.location.lat; lng = data.results[0].geometry.location.lng; location = data.results[0].formatted_address; } var newCampground = {name: name, price: price, image: image, description: description, author: author, location: location, lat: lat, lng: lng}; //create Campground.create(newCampground, function(err, result) { if(err) { console.log(err); } else { console.log(result); res.redirect('/campgrounds'); } }); }); }); });<% include ../partials/header %> <div> <h1>Create a New CampGround</h1> <div style='width: 30%; margin: 30px auto;'> <form action='/campgrounds' method='POST' enctype="multipart/form-data"> <div class='form-group'> <label for="name">Name</label> <input type='text' name='name' placeholder='Name'> </div> <div class='form-group'> <label for="price">Price</label> <input type='number' name='price' placeholder='price' min="0.01" step="0.01"> </div> <div class='form-group'> <label for="image">Image</label> <input type="file" name="image" accept="image/*" required> </div> <div class='form-group'> <label for="description">Description</label> <input type='text' name='description' placeholder='Write description'> </div> <div> <label for="location">Location</label> <input type="text" name="location" placeholder="Yosemite National Park, CA"> </div> <div class='form-group'> <button>Submit!</button> </div> </form> <a href="/campgrounds"> Go Back </a> </div> </div> <% include ../partials/footer %>26 Answers
The cloudinary config values must be in strings otherwise they won't work. Configure your code either of these ways in your cloudinary segment:
1a: CloudinaryConfig.js:
cloudinary.config({ cloud_name: process.env.CLOUD_NAME, api_key: process.env.CLOUD_KEY, api_secret: process.env.CLOUD_SECRET }); 1b: .env
CLOUDINARY_CLOUD_NAME='sample' CLOUDINARY_API_KEY='874837483274837' CLOUDINARY_API_SECRET='a676b67565c6767a6767d6767f676fe1' 2: Putting your cloudinary-supplied values directly into the code:
cloudinary.config({ cloud_name: 'sample', api_key: '874837483274837', api_secret: 'a676b67565c6767a6767d6767f676fe1' }); NOTE: Ensure that you don't expose your config values for security reasons. If you're committing code to a public repo like github, use .gitignore to leave out whatever file where you store your secret info.
Checkout the cloudinary docs for more reference: .
The reason can be your js file where you would have not included require('dotenv').config(); Try adding this and then run your code.
Can you try putting the API key directly in your code and see if that works. You could also add a print statement and see what response you get for API key
1The dotenv must be required up top where you are using your process.env.API_KEY:
require("dotenv").config(); 1If you're using a NodeJS server-side function to upload, ensure you've installed the dotenv package;
yarn add dotenv Thereafter, put the cloudinary variables in a '.env' file. From the file (controller) where you're to make the upload, you must point to dotenv, to that file, relative to where your package.json file is sitting. Here's an instance for me, trying to make an upload from 'CompanyControllers.ts'
import dotenv from "dotenv"; dotenv.config({path: "./backend/src/settings/controllers/CompanyControllers.ts"}); So, if I do;
console.log("\n\t Cloud name: ", process.env.CLOUDINARY_UPLOAD_CLOUD_NAME) .....my cloudinary cloud name is logged const cloudinaryResponse = await cloudinary.v2.uploader.upload(filePath, { cloud_name: process.env.CLOUDINARY_UPLOAD_CLOUD_NAME, api_secret: process.env.CLOUDINARY_UPLOAD_API_SECRET, upload_preset: process.env.CLOUDINARY_UPLOAD_PRESET_NAME, api_key: process.env.CLOUDINARY_UPLOAD_API_KEY, resource_type: "image", secure: true }); use this
const dotenv = require('dotenv'); dotenv.config();
2