Installation
npm install @apexxcloud/sdk-js
Initialization
import ApexxCloud from "@apexxcloud/sdk-js";
const storage = new ApexxCloud({
baseUrl: "https://api.apexxcloud.com", // optional
});
Backend Implementation
Your backend needs to implement an endpoint that generates signed URLs. Here’s an example using Node.js:
const ApexxCloud = require("@apexxcloud/sdk-node");
const storage = new ApexxCloud({
accessKey: process.env.APEXXCLOUD_ACCESS_KEY,
secretKey: process.env.APEXXCLOUD_SECRET_KEY,
region: "bucket-region",
bucket: "bucket-name",
});
app.post("/api/get-signed-url/:type", async (req, res) => {
try {
const { type } = req.params;
const params = req.body; // Contains key, mimeType, totalParts, etc.
const signedUrl = await storage.getSignedUrl(
"your-bucket-name",
params.key,
{
type: type,
...params,
}
);
res.send(signedUrl);
} catch (error) {
res.status(500).send(error.message);
}
});
The endpoint should handle these types of requests:
Type | Description | Required Parameters | Example Response |
---|
upload | Single file upload | key, mimeType | https://api.apexxcloud.com/upload?signature=... |
start-multipart | Start multipart upload | key, totalParts, mimeType | https://api.apexxcloud.com/multipart/start?signature=... |
uploadpart | Upload individual part | uploadId, partNumber, key, totalParts | https://api.apexxcloud.com/multipart/{uploadId}/upload?signature=... |
completemultipart | Complete multipart upload | uploadId, key | https://api.apexxcloud.com/multipart/{uploadId}/complete?signature=... |
cancelmultipart | Cancel multipart upload | uploadId, key | https://api.apexxcloud.com/multipart/{uploadId}/cancel?signature=... |
File Upload
Basic Upload
const controller = new AbortController();
// Function to get signed URLs from your backend
const getSignedUrl = async (type, params) => {
const response = await fetch(`/api/get-signed-url/${type}`, {
method: "POST",
body: JSON.stringify(params),
});
return response.text();
};
try {
const result = await storage.files.upload(getSignedUrl, file, {
signal: controller.signal,
onStart: (event) => {
console.log("Upload started:", event);
// event.type: 'start'
// event.timestamp: Start time
// event.file: {
// name: string,
// size: number,
// type: string
// }
},
onProgress: (event) => {
console.log(`Upload progress: ${event.progress}%`);
// event.loaded: Bytes uploaded
// event.total: Total bytes
// event.progress: Percentage complete (0-100)
// event.type: 'progress'
},
onComplete: (event) => {
console.log("Upload completed:", event);
// event.type: 'complete'
// event.response: Server response
// event.timestamp: Completion time
// event.file: File metadata
},
onError: (event) => {
console.error("Upload failed:", event);
// event.type: 'error' | 'abort'
// event.error: Error object
// event.timestamp: Error time
// event.status?: HTTP status code (if applicable)
},
});
} catch (error) {
console.error("Upload failed:", error);
}
// To cancel the upload:
controller.abort();
Multipart Upload
const controller = new AbortController();
try {
const result = await storage.files.uploadMultipart(getSignedUrl, file, {
signal: controller.signal,
partSize: 5 * 1024 * 1024, // 5MB chunks (optional)
concurrency: 3, // Number of concurrent uploads (optional)
onProgress: (event) => {
console.log(`Total progress: ${event.progress}%`);
console.log(
`Part ${event.part.number} progress: ${event.part.progress}%`
);
// event.loaded: Total bytes uploaded
// event.total: Total file size
// event.progress: Overall percentage
// event.part: {
// number: Current part number
// progress: Current part progress (0-100)
// }
},
onPartComplete: (part) => {
console.log("Part completed:", part);
// part.ETag: Part ETag from server
// part.PartNumber: Completed part number
},
onComplete: (event) => {
console.log("Upload completed:", event);
// event.type: 'complete'
// event.response: Server response
// event.timestamp: Completion time
// event.file: File metadata
},
onError: (event) => {
console.error("Upload error:", event);
// event.type: 'error' | 'abort'
// event.error: Error object
// event.phase: 'start' | 'upload' | 'complete' | 'cancel'
// event.status?: HTTP status code (if applicable)
// event.timestamp: Error time
},
});
} catch (error) {
console.error("Upload failed:", error);
}
Error Handling
The SDK provides detailed error information through the onError callback:
try {
await storage.files.upload(getSignedUrl, file, {
onError: (event) => {
if (event.type === "abort") {
console.log("Upload was cancelled");
} else {
console.error("Upload failed:", event.error.message);
if (event.status) {
console.error("HTTP Status:", event.status);
}
if (event.phase) {
// For multipart uploads
console.error("Failed during phase:", event.phase);
}
}
},
});
} catch (error) {
console.error("Upload failed:", error.message);
}
Multipart Upload Phases
The multipart upload process includes different phases where errors might occur:
Phase | Description |
---|
start | During the initialization of multipart upload |
upload | During the upload of individual parts |
complete | During the completion of multipart upload |
cancel | During attempt to cancel a failed upload |
The SDK provides a powerful image transformation API that allows you to modify images on-the-fly:
const storage = new ApexxCloud({
accessId: "your-access-id",
cdnUrl: "https://cdn.apexxcloud.com", // optional
});
// Basic transformations
const url = storage.transformimage
.width(800)
.height(600)
.crop("fill")
.quality("auto:good")
.buildUrl("path/to/image.jpg");
// Chaining multiple transformations
const complexUrl = storage.transformimage
.width(800)
.height(600)
.crop("fill")
.chain()
.blur(20)
.grayscale()
.buildUrl("path/to/image.jpg");
// Text overlay
const withText = storage.transformimage
.text("Hello World", {
font: "Arial",
size: 32,
color: "#FFFFFF",
gravity: "center",
opacity: 100,
})
.buildUrl("path/to/image.jpg");
// Image overlay
const withImage = storage.transformimage
.overlay("path/to/logo.png", {
type: "image",
gravity: "southeast",
x: 20,
y: 20,
width: 100,
opacity: 80,
})
.buildUrl("path/to/image.jpg");
Transformation | Method | Parameters | Example |
---|
Width | width(value) | 1-5000px | .width(800) |
Height | height(value) | 1-5000px | .height(600) |
Crop | crop(mode) | ’fill’, ‘fit’, ‘scale’ | .crop('fill') |
Quality | quality(value) | 1-100 or auto modes | .quality('auto:good') |
Format | format(type) | ’auto’, ‘webp’, ‘jpeg’ | .format('webp') |
Blur | blur(radius) | 1-100 | .blur(20) |
Grayscale | grayscale() | - | .grayscale() |
Background | background(color) | hex or ‘transparent’ | .background('#ff0000') |
Border | border(width, style, color) | width, style, color | .border(2, 'solid', '#000') |
Radius | radius(value) | pixels or array | .radius(10) |
Opacity | opacity(value) | 0-100 | .opacity(50) |
Text Overlay | text(text, options) | text, options | .text('Hello', options) |
Image Overlay | overlay(path, options) | path, options | .overlay('logo.png', options) |
Overlay Options
Option | Type | Description | Supported Types |
---|
type | string | ’image’ or ‘video’ | Video only |
gravity | string | Position on target | All |
x | number | Horizontal offset | All |
y | number | Vertical offset | All |
scale | number | Scale factor | Image, Video |
width | number | Width in pixels | Image, Video |
height | number | Height in pixels | Image, Video |
opacity | number | Opacity (0-100) | All |
aspectRatio | string | Aspect ratio | Image, Video |
Text-specific options:
Option | Type | Description |
---|
font | string | Font family name |
size | number | Font size in pixels |
color | string | Text color (hex) |
Similar to images, you can transform videos:
// Basic video transformation
const videoUrl = storage.transformvideo
.width(1280)
.height(720)
.format("mp4")
.buildUrl("path/to/video.mp4");
// Generate video thumbnail
const thumbnailUrl = storage.transformvideo
.thumbnail(5.0) // Seek to 5 seconds
.width(400)
.height(300)
.crop("fill")
.buildUrl("path/to/video.mp4");
// Text overlay
const withText = storage.transformvideo
.text("Hello World", {
font: "Arial",
size: 32,
color: "#FFFFFF",
gravity: "center",
opacity: 100,
})
.buildUrl("path/to/video.mp4");
// Image overlay
const withImage = storage.transformvideo
.overlay("path/to/logo.png", {
type: "image",
gravity: "southeast",
x: 20,
y: 20,
width: 100,
opacity: 80,
})
.buildUrl("path/to/video.mp4");
// Video overlay (for videos only)
const withVideoOverlay = storage.transformvideo
.overlay("path/to/overlay.mp4", {
type: "video",
gravity: "center",
width: 200,
height: 200,
opacity: 70,
})
.buildUrl("path/to/video.mp4");
Transformation | Method | Parameters | Example |
---|
Width | width(value) | 1-5000px | .width(1280) |
Height | height(value) | 1-5000px | .height(720) |
Format | format(type) | ’mp4’, ‘webm’, ‘mov’ | .format('mp4') |
Thumbnail | thumbnail(seekOffset) | seconds | .thumbnail(5.0) |
Crop | crop(mode) | ’crop’, ‘fill’, ‘fit’ | .crop('fill') |
Background | background(color) | hex or ‘blur’ | .background('blur') |
Text Overlay | text(text, options) | text, options | .text('Title', options) |
Image Overlay | overlay(path, options) | path, options | .overlay('logo.png', imageOpts) |
Video Overlay | overlay(path, options) | path, options | .overlay('intro.mp4', videoOpts) |
Overlay Options
Option | Type | Description | Supported Types |
---|
type | string | ’image’ or ‘video’ | Video only |
gravity | string | Position on target | All |
x | number | Horizontal offset | All |
y | number | Vertical offset | All |
scale | number | Scale factor | Image, Video |
width | number | Width in pixels | Image, Video |
height | number | Height in pixels | Image, Video |
opacity | number | Opacity (0-100) | All |
aspectRatio | string | Aspect ratio | Image, Video |
Text-specific options:
Option | Type | Description |
---|
font | string | Font family name |
size | number | Font size in pixels |
color | string | Text color (hex) |
Transform and convert documents:
// Convert document format
const pdfUrl = storage.transformdocument
.format("pdf")
.quality("auto:high")
.buildUrl("path/to/document.docx");
// Generate document thumbnail
const thumbnailUrl = storage.transformdocument
.thumbnail(1) // First page
.width(800)
.height(1200)
.buildUrl("path/to/document.pdf");
Transformation | Method | Parameters | Example |
---|
Format | format(type) | ’pdf’, ‘docx’, ‘xlsx’, ‘pptx’ | .format('pdf') |
Quality | quality(mode) | ’auto:high’, ‘auto:standard’, ‘auto:low’ | .quality('auto:high') |
Compress | compress(mode) | ’high’, ‘medium’, ‘low’ | .compress('medium') |
Pages | pages(range) | number or range (‘1-3,5-7’) | .pages('1-3') |
Thumbnail | thumbnail(page) | Page number | .thumbnail(1) |
You can chain multiple transformations together using the chain()
method:
const url = storage.transformimage
.width(800)
.height(600)
.crop("fill")
.chain()
.blur(20)
.grayscale()
.buildUrl("path/to/image.jpg");
Each transformation chain is applied sequentially, allowing for complex transformation pipelines.