Spaces:
Running
Running
Download cloudinaryUpload.js from AndreaNotes1/auth-app-api: direct link, hf CLI and curl.
- Browser
- Download file 3.49 kB
-
https://huggingface.co/spaces/AndreaNotes1/auth-app-api/resolve/main/cloudinaryUpload.js
- Command line
-
hf download hf://spaces/AndreaNotes1/auth-app-api/cloudinaryUpload.js
-
curl -L -o cloudinaryUpload.js https://huggingface.co/spaces/AndreaNotes1/auth-app-api/resolve/main/cloudinaryUpload.js
3.49 kB
| const fs = require("fs"); | |
| const cloudinary = require("../config/cloudinary"); | |
| const FOLDER = "aynwerd-courses"; | |
| // Cloudinary's chunked `upload_large` is meant for genuinely large | |
| // files (their own docs point to it for anything that risks a single | |
| // request timing out or exceeding size limits β 100MB+ in practice). | |
| // Using it unconditionally for every video was a bug: for small files | |
| // its resolved result can come back missing fields (public_id, | |
| // resource_type) that the plain, non-chunked upload always includes, | |
| // which surfaced as a confusing Mongoose "required" validation error | |
| // rather than a clear upload error. Only use it above this threshold. | |
| const LARGE_UPLOAD_THRESHOLD_BYTES = 100 * 1024 * 1024; // 100MB | |
| /** | |
| * Uploads a file from a local temp path to Cloudinary under private, | |
| * signed-only access. `type: "authenticated"` means the asset can | |
| * NEVER be fetched by its plain URL or by guessing the public ID β | |
| * every request must carry a valid signature that we only ever mint | |
| * for a verified, paying learner (see getSignedPlaybackUrl below). | |
| */ | |
| async function uploadFromPath(filePath, { resourceType, filenameHint }) { | |
| const options = { | |
| folder: FOLDER, | |
| resource_type: resourceType, // "video" | "image" | "raw" | |
| type: "authenticated", | |
| use_filename: true, | |
| unique_filename: true, | |
| filename_override: filenameHint, | |
| }; | |
| const { size } = fs.statSync(filePath); | |
| const useLargeUpload = resourceType === "video" && size > LARGE_UPLOAD_THRESHOLD_BYTES; | |
| const result = useLargeUpload | |
| ? await cloudinary.uploader.upload_large(filePath, { ...options, chunk_size: 20 * 1024 * 1024 }) | |
| : await cloudinary.uploader.upload(filePath, options); | |
| // Fail loudly and specifically here rather than letting an | |
| // incomplete result silently reach the database, where it would | |
| // otherwise surface as an opaque Mongoose validation error instead | |
| // of a clear "the upload didn't actually succeed" message. | |
| if (!result || !result.public_id || !result.resource_type) { | |
| throw new Error( | |
| `Cloudinary upload did not return the expected result (got: ${JSON.stringify(result)}). ` + | |
| "The file was not saved β please try again." | |
| ); | |
| } | |
| return result; | |
| } | |
| function deleteAsset(publicId, resourceType) { | |
| return cloudinary.uploader.destroy(publicId, { resource_type: resourceType, type: "authenticated" }); | |
| } | |
| /** | |
| * Mints a short-lived, signed URL for a specific lesson asset. Valid for | |
| * a couple of hours only, so a leaked link stops working quickly and | |
| * cannot be redistributed as a permanent download. | |
| */ | |
| function getSignedPlaybackUrl(publicId, resourceType, { format, expiresInSeconds = 2 * 60 * 60 } = {}) { | |
| const expiresAt = Math.floor(Date.now() / 1000) + expiresInSeconds; | |
| const url = cloudinary.url(publicId, { | |
| resource_type: resourceType, | |
| type: "authenticated", | |
| sign_url: true, | |
| secure: true, | |
| expires_at: expiresAt, | |
| format: format || undefined, | |
| }); | |
| return { url, expiresAt }; | |
| } | |
| /** Maps an uploaded file's mimetype to the Cloudinary resource_type bucket it belongs in. */ | |
| function resourceTypeForMimetype(mimetype) { | |
| if (mimetype.startsWith("video/")) return "video"; | |
| if (mimetype.startsWith("image/")) return "image"; | |
| return "raw"; // PDFs, docs, slides, zips, etc. | |
| } | |
| module.exports = { uploadFromPath, deleteAsset, getSignedPlaybackUrl, resourceTypeForMimetype }; | |