upcloud
v1.1.7
Published
A powerful and user friendly npm package for smooth file management and uploads with Cloudinary that integrates Multer to process incoming file requests.
Downloads
22
Maintainers
Readme
upcloud
A powerful and user friendly npm package for smooth file management and uploads with Cloudinary that integrates Multer to process incoming file requests.
Badges
Key Features
- Effortless Cloudinary Integration: Easily upload and manage files on Cloudinary
- Multer Middleware: Seamlessly integrate with Express.js for handling
multipart/form-dataprimarily for file uploads - Flexible Upload Options: Supports single and multiple file uploads with options for specifying folders and resource types
- File Deletion: Conveniently delete files from Cloudinary using their public IDs
- Comprehensive Error Handling: Provides detailed error responses for robust application development
- Multiple Upload Methods: Supports uploading from local paths, buffers, and streams, including a dedicated function for large files
- Dual Module Support: Works seamlessly with both CommonJS (
require) and ES Modules (import)
Installation
You can install upcloud using npm or yarn:
npm install upcloud
# or
yarn add upcloudAdditionally, for Express.js integration, you'll need express and dotenv (for environment variables):
npm install express dotenvUsage
1. Configure Cloudinary
Before using any upload functions, you need to configure your Cloudinary credentials. It's recommended to use environment variables.
Create a .env file in your project root:
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secretCommonJS (.js file):
const { configureCloudinary } = require("upcloud");
const dotenv = require("dotenv");
dotenv.config();
configureCloudinary({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});ES Modules (.mjs file):
import { configureCloudinary } from "upcloud";
import dotenv from "dotenv";
dotenv.config();
configureCloudinary({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});2. Express.js Integration with Multer
This demonstrates setting up an Express server to handle file uploads via HTTP POST requests.
CommonJS (server.js):
const express = require("express");
const dotenv = require("dotenv");
const fs = require("fs/promises");
const {
configureCloudinary,
createMulterDiskMiddleware,
uploadFile,
uploadMultipleFiles,
} = require("upcloud");
dotenv.config();
configureCloudinary({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
const app = express();
const port = 3000;
const upload = createMulterDiskMiddleware({ dest: "./uploads" });
fs.mkdir("./uploads", { recursive: true }).catch(console.error);
// single file upload
app.post("/upload-single", upload.single("image"), async (req, res) => {
if (!req.file) return res.status(400).json({ message: "No file uploaded" });
try {
const result = await uploadFile(req.file.path, {
folder: "express-uploads",
});
await fs.unlink(req.file.path);
res.status(result.statusCode).json(result);
} catch (error) {
console.error("Upload error:", error);
res
.status(500)
.json({ message: "File upload failed", error: error.message });
}
});
// multiple files upload
app.post("/upload-multiple", upload.array("images", 5), async (req, res) => {
if (!req.files || req.files.length === 0)
return res.status(400).json({ message: "No files uploaded" });
const filePaths = req.files.map((file) => file.path);
try {
const results = await uploadMultipleFiles(filePaths, {
folder: "express-multiple-uploads",
});
await Promise.all(filePaths.map((p) => fs.unlink(p)));
res.status(200).json({
status: true,
statusCode: 200,
message: "Files uploaded successfully",
data: results,
});
} catch (error) {
console.error("Multiple upload error:", error);
res
.status(500)
.json({ message: "Multiple file upload failed", error: error.message });
}
});
app.listen(port, () =>
console.log(`Server running on http://localhost:${port}`)
);ES Modules (server.mjs):
import express from "express";
import dotenv from "dotenv";
import fs from "fs/promises";
import { fileURLToPath } from "url";
import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
import {
configureCloudinary,
createMulterDiskMiddleware,
uploadFile,
uploadMultipleFiles,
} from "upcloud";
dotenv.config();
configureCloudinary({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
const app = express();
const port = 3000;
const upload = createMulterDiskMiddleware({ dest: "./uploads" });
fs.mkdir("./uploads", { recursive: true }).catch(console.error);
app.post("/upload-single", upload.single("image"), async (req, res) => {
if (!req.file) return res.status(400).json({ message: "No file uploaded" });
try {
const result = await uploadFile(req.file.path, {
folder: "express-uploads-esm",
});
await fs.unlink(req.file.path);
res.status(result.statusCode).json(result);
} catch (error) {
console.error("Upload error:", error);
res
.status(500)
.json({ message: "File upload failed", error: error.message });
}
});
app.post("/upload-multiple", upload.array("images", 5), async (req, res) => {
if (!req.files || req.files.length === 0)
return res.status(400).json({ message: "No files uploaded" });
const filePaths = req.files.map((file) => file.path);
try {
const results = await uploadMultipleFiles(filePaths, {
folder: "express-multiple-uploads-esm",
});
await Promise.all(filePaths.map((p) => fs.unlink(p)));
res.status(200).json({
status: true,
statusCode: 200,
message: "Files uploaded successfully",
data: results,
});
} catch (error) {
console.error("Multiple upload error:", error);
res
.status(500)
.json({ message: "Multiple file upload failed", error: error.message });
}
});
app.listen(port, () =>
console.log(`Server running on http://localhost:${port}`)
);To test the Express routes:
- Start the server:
node server.js(for CommonJS) ornode server.mjs(for ES Modules) - Use
curlor a tool like Postman/Insomnia to sendmultipart/form-datarequests- Single file:
curl -X POST -F 'image=@./path/to/your/image.jpg' http://localhost:3000/upload-single - Multiple files:
curl -X POST -F 'images=@./path/to/doc1.pdf' -F 'images=@./path/to/doc2.pdf' http://localhost:3000/upload-multiple
- Single file:
3. Direct File Operations
These examples show how to use the upcloud functions directly without an Express server.
CommonJS (app.js):
const {
configureCloudinary,
uploadFile,
uploadMultipleFiles,
deleteFile,
} = require("upcloud");
const {
uploadFromPath,
uploadBuffer,
uploadStream,
uploadLarge,
cloudinary,
} = require("upcloud/cloudinaryClient");
const dotenv = require("dotenv");
const path = require("path");
const fs = require("fs");
dotenv.config();
configureCloudinary({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
async function runDirectExamples() {
const imagePath = path.join(__dirname, "test-image.jpg");
const docPaths = [
path.join(__dirname, "test-doc1.pdf"),
path.join(__dirname, "test-doc2.pdf"),
];
const videoPath = path.join(__dirname, "test-video.mp4");
let uploadedPublicId = null;
// Example: Upload Single File
try {
const response = await uploadFile(imagePath, { folder: "direct-commonjs" });
console.log("Upload successful:", response.data[0].secure_url);
uploadedPublicId = response.data[0].public_id;
} catch (error) {
console.error("Upload failed:", error.message);
}
// Example: Upload Multiple Files
try {
const results = await uploadMultipleFiles(docPaths, {
folder: "direct-commonjs-docs",
});
results.forEach((res) => console.log(res.secure_url));
} catch (error) {
console.error("Multiple uploads failed:", error.message);
}
// Example: Upload from Buffer
try {
const buffer = Buffer.from("This is a test text file from a buffer.");
const result = await uploadBuffer(buffer, {
resource_type: "raw",
public_id: "buffer-test-commonjs",
});
console.log("Buffer upload successful:", result.secure_url);
} catch (error) {
console.error("Buffer upload failed:", error.message);
}
// Example: Upload from Stream
try {
const readableStream = fs.createReadStream(videoPath);
const result = await uploadStream(readableStream, {
resource_type: "video",
folder: "stream-commonjs",
});
console.log("Stream upload successful:", result.secure_url);
} catch (error) {
console.error("Stream upload failed:", error.message);
}
// Example: Delete File
if (uploadedPublicId) {
try {
const result = await deleteFile(uploadedPublicId);
console.log("Deletion successful:", result);
} catch (error) {
console.error("Deletion failed:", error.message);
}
} else {
}
// Example: Using raw cloudinary instance
try {
const resources = await cloudinary.api.resources({
type: "upload",
max_results: 3,
});
console.log(
"First 3 uploaded resources:",
resources.resources.map((r) => r.public_id)
);
} catch (error) {
console.error("Failed to list resources:", error.message);
}
}
runDirectExamples();ES Modules (app.mjs):
import {
configureCloudinary,
uploadFile,
uploadMultipleFiles,
deleteFile,
} from "upcloud";
import {
uploadFromPath,
uploadBuffer,
uploadStream,
uploadLarge,
cloudinary,
} from "upcloud/cloudinaryClient";
import dotenv from "dotenv";
import path from "path";
import fs from "fs";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
dotenv.config();
configureCloudinary({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
async function runDirectExamples() {
const imagePath = path.join(__dirname, "test-image.jpg");
const docPaths = [
path.join(__dirname, "test-doc1.pdf"),
path.join(__dirname, "test-doc2.pdf"),
];
const videoPath = path.join(__dirname, "test-video.mp4");
let uploadedPublicId = null;
try {
const response = await uploadFile(imagePath, { folder: "direct-esm" });
console.log("Upload successful:", response.data[0].secure_url);
uploadedPublicId = response.data[0].public_id;
} catch (error) {
console.error("Upload failed:", error.message);
}
try {
const results = await uploadMultipleFiles(docPaths, {
folder: "direct-esm-docs",
});
results.forEach((res) => console.log(res.secure_url));
} catch (error) {
console.error("Multiple uploads failed:", error.message);
}
try {
const buffer = Buffer.from("This is a test text file from a buffer (ESM).");
const result = await uploadBuffer(buffer, {
resource_type: "raw",
public_id: "buffer-test-esm",
});
console.log("Buffer upload successful:", result.secure_url);
} catch (error) {
console.error("Buffer upload failed:", error.message);
}
try {
const readableStream = fs.createReadStream(videoPath);
const result = await uploadStream(readableStream, {
resource_type: "video",
folder: "stream-esm",
});
console.log("Stream upload successful:", result.secure_url);
} catch (error) {
console.error("Stream upload failed:", error.message);
}
// Example: Delete File
if (uploadedPublicId) {
try {
const result = await deleteFile(uploadedPublicId);
console.log("Deletion successful:", result);
} catch (error) {
console.error("Deletion failed:", error.message);
}
} else {
}
// Example: Using raw cloudinary instance
try {
const resources = await cloudinary.api.resources({
type: "upload",
max_results: 3,
});
console.log(
"First 3 uploaded resources:",
resources.resources.map((r) => r.public_id)
);
} catch (error) {
console.error("Failed to list resources:", error.message);
}
}
runDirectExamples();To run these direct usage examples:
- For CommonJS:
node app.js - For ES Modules:
node app.mjs
Available Functions and Options
| Function / Interface | Description | Parameters | Returns |
| :--------------------------- | :------------------------------------------------------------------------------------------------ | :-------------------------------------------------------- | :----------------------------------------------------------------------- |
| configureCloudinary | Configures the Cloudinary SDK with your credentials. | config: CloudinaryConfig | void |
| createMulterDiskMiddleware | Creates a Multer middleware instance configured for disk storage. | options?: multer.Options (Multer options) | multer.Multer instance |
| uploadFile | Uploads a single file from a local path to Cloudinary. | filePath: string, options?: UploadApiOptions | { status: boolean; statusCode: number; message: string; data: any[]; } |
| uploadMultipleFiles | Uploads an array of files from local paths to Cloudinary. | filePaths: string[], options?: UploadApiOptions | Promise<UploadApiResponse[]> |
| deleteFile | Deletes a file from Cloudinary using its public ID. | publicId: string, options?: UploadApiOptions | Promise<UploadApiResponse> |
| uploadFromPath | (Advanced) Uploads a file from a local path. Returns raw Cloudinary response. | localPath: string, opts?: Record<string, any> | Promise<UploadResult> |
| uploadBuffer | (Advanced) Uploads a file from a Buffer. Returns raw Cloudinary response. | buffer: Buffer, opts?: Record<string, any> | Promise<UploadResult> |
| uploadStream | (Advanced) Uploads a file from a Readable Stream. Returns raw Cloudinary response. | readable: stream.Readable, opts?: Record<string, any> | Promise<UploadResult> |
| uploadLarge | (Advanced) Uploads a very large file (>100MB) from a local path. Returns raw Cloudinary response. | localPath: string, opts?: Record<string, any> | Promise<UploadResult> |
| cloudinary | (Advanced) The raw configured Cloudinary SDK instance for direct API calls. | N/A | cloudinary.v2 instance |
CloudinaryConfig Interface
| Property | Type | Description | Required |
| :----------- | :------- | :-------------------------- | :------- |
| cloud_name | string | Your Cloudinary cloud name. | Yes |
| api_key | string | Your Cloudinary API key. | Yes |
| api_secret | string | Your Cloudinary API secret. | Yes |
UploadApiOptions Interface
| Property | Type | Description | Required |
| :-------------- | :------------------------------------------------------- | :------------------------------------------------------------------------------------------------ | :------- |
| folder | string | The name of the folder in your Cloudinary account to upload the file to. | No |
| resource_type | ResourceType ("image" \| "video" \| "raw" \| "auto") | The type of resource being uploaded. Defaults to "image". Use "auto" for automatic detection. | No |
UploadApiResponse Interface
| Property | Type | Description |
| :------------ | :------- | :------------------------------------------- |
| public_id | string | The public ID of the uploaded asset. |
| secure_url | string | The secure URL of the uploaded asset. |
| [k: string] | any | Other properties returned by Cloudinary API. |
Contribution
Contributions are welcome. If you have suggestions for improvements, bug fixes or new features please open an issue or submit a pull request.
- Fork the repository
- Create a new branch (
git checkout -b feature/your-feature) - Make your changes
- Commit your changes (
git commit -m 'Add new feature') - Push to the branch (
git push origin feature/your-feature) - Open a pull request
License
This project is licensed under the MIT License - see the LICENSE file for details.
