# File Upload Guide

The CKBox Node.js SDK provides file upload capabilities with support for multiple upload methods, categorization, progress tracking, and concurrent upload management.

<a id="upload-methods-overview">

## Upload Methods Overview

The SDK offers three primary upload methods:

| Method                                  | Use Case              | Input Type           |
| --------------------------------------- | --------------------- | -------------------- |
| [`uploadFile()`](#upload-from-file)     | Upload from file path | File system path     |
| [`uploadBuffer()`](#upload-from-buffer) | Upload from memory    | Buffer object        |
| [`uploadStream()`](#upload-file-stream) | Upload from stream    | ReadStream or Buffer |

All methods support:

* **Progress tracking** with real-time callbacks
* **Categorization** and folder organization
* **Concurrent uploads** with automatic queue management
* **Error handling** with detailed error information

<a id="basic-upload-examples">

## Basic Upload Examples

<a id="upload-from-file">

### Upload from File

The simplest way to upload a file is using `uploadFile()` with a file system path.

```javascript
import CKBox from '@ckbox/sdk-node';

const ckbox = new CKBox({
  accessKey: process.env.CKBOX_ACCESS_KEY,
  environmentId: process.env.CKBOX_ENVIRONMENT_ID
});

// Basic file upload
async function uploadImage() {
  try {
	const result = await ckbox.uploader.uploadFile('./images/photo.jpg');
	
	console.log('Upload successful!');
	console.log('Asset ID:', result.id);
	console.log('File URL:', result.url);
	console.log('File size:', result.size);
	
	return result;
  } catch (error) {
	console.error('Upload failed:', error.message);
	throw error;
  }
}
```

<a id="upload-from-buffer">

### Upload from Buffer

Upload files that are already in memory as Buffer objects, useful for dynamically generated content.

```javascript
import fs from 'fs';

async function uploadFromBuffer() {
  // Read file into buffer
  const fileBuffer = fs.readFileSync('./image.png');
  
  const result = await ckbox.uploader.uploadBuffer(
	fileBuffer,
	'my-image.png'
  );
  
  console.log('Buffer uploaded successfully:', result.id);
  return result;
}
```

<a id="upload-file-stream">

### Upload File Stream

Use streams for memory-efficient uploads of large files, especially useful when processing large media files.

```javascript
import fs from 'fs';

async function uploadFileStream() {
  const filePath = './large-video.mp4';
  const stream = fs.createReadStream(filePath);
  
  const result = await ckbox.uploader.uploadStream(
	stream,
	'large-video.mp4'
  );
  
  console.log('Stream upload completed:', result.id);
  return result;
}
```

<a id="upload-to-specific-category">

### Upload to specific category

Organize uploads by assigning them to predefined categories to help structure your file organization.

```javascript
async function uploadToCategory() {
  const result = await ckbox.uploader.uploadFile('./document.pdf', {
	categoryId: '{{categoryId}}'
  });
  
  console.log('Document uploaded to category:', result.categoryId);
  return result;
}
```

<a id="upload-to-specific-folder">

### Upload to specific folder

Upload files directly to a specific folder within a category for more granular organization.

```javascript
async function uploadToFolder() {
  const result = await ckbox.uploader.uploadFile('./report.xlsx', {
	folderId: '{{folderId}}'
  });
  
  console.log('File uploaded to folder:', result.folderId);
  return result;
}
```

<a id="upload-with-progress-tracking">

### Upload with progress tracking

Monitor upload progress in real-time with callback functions to update your UI or log progress.

```javascript
async function uploadWithProgress() {
  const result = await ckbox.uploader.uploadFile('./large-file.mp4', {
	onProgress: (progress) => {
	  const { loaded, total, progress: percent } = progress;
	  console.log(`Progress: ${percent}% (${loaded}/${total} bytes)`);
	  
	  // Update progress bar in your UI
	  updateProgressBar(percent);
	}
  });
  
  console.log('Upload completed:', result.id);
  return result;
}

function updateProgressBar(percent) {
  const progressBar = '█'.repeat(Math.floor(percent / 5));
  const empty = '░'.repeat(20 - Math.floor(percent / 5));
  console.log(`[${progressBar}${empty}] ${percent}%`);
}
```

<a id="multi-file-upload">

### Multi-File upload

Handle batch uploads by processing multiple files sequentially with comprehensive error handling.

```javascript
async function uploadMultipleFilesSequential(filePaths) {
  const results = [];
  
  for (const filePath of filePaths) {
	try {
	  console.log(`Uploading: ${filePath}`);
	  
	  const result = await ckbox.uploader.uploadFile(filePath, {
		onProgress: (progress) => {
		  console.log(`${filePath}: ${progress.progress}%`);
		}
	  });
	  
	  results.push(result);
	  console.log(`✅ Completed: ${filePath}`);
	  
	} catch (error) {
	  console.error(`❌ Failed: ${filePath}`, error.message);
	  results.push({ error: error.message, filePath });
	}
  }
  
  return results;
}

// Usage
const files = ['./image1.jpg', './image2.png', './document.pdf'];
const results = await uploadMultipleFilesSequential(files);
```

<a id="upload-response">

## Upload response

Every successful file upload returns a `CKBoxAsset` object representing the uploaded file. Note that some properties like image metadata are processed asynchronously after upload, so metadata fields may be populated with a delay.

```typescript
interface CKBoxAsset {
	id: string;				   // Unique identifier for the asset
	name: string;			   // Original filename with extension
	categoryId: string;		   // ID of the category where the file is stored
	folderId?: string;		   // Optional folder ID within the category
	imageUrls?: {			   // Generated image variants (thumbnails, resized versions)
		[key: string]: string; // Size name mapped to image URL
	};
	url: string;			   // Direct access URL to the file
	size: number;			   // File size in bytes
	lastUsedAt: string;		   // ISO timestamp when the asset was last accessed
	lastModifiedAt: string;	   // ISO timestamp when the asset was uploaded/modified
	path: string;			   // Full path within CKBox storage structure
	tags: string[];			   // Array of tags associated with the asset
	metadata?: {			   // Optional metadata (populated asynchronously for images)
	  width?: number;		   // Image width in pixels
	  height?: number;		   // Image height in pixels
	  metadataProcessingStatus?: string; // Processing status: 'queued', 'success', 'error',
	  analysisProcessingStatus?: string; // AI processing status (if applicable): 'queued', 'success', 'error', 'skipped'
	};
}
```

---

Full index of the CKBox documentation: [llms.txt](../../../../llms.txt)
