Installation
Install the Filejar client and required dependencies:Copy
npm install filejar fastify @fastify/multipart
Setup
Create Filejar Client
Initialize the Filejar client in your Fastify application:Copy
import Fastify from 'fastify';
import Filejar from 'filejar';
const app = Fastify();
// Initialize Filejar client
const filejar = new Filejar({
apiKey: process.env.FILEJAR_API_KEY,
});
// Register multipart plugin for file uploads
await app.register(import('@fastify/multipart'), {
limits: {
fileSize: 10 * 1024 * 1024, // 10MB limit
},
});
Single File Upload Endpoint
Create an endpoint to upload a single file:Copy
import { fileRepo } from '@/lib/db-repo';
// Single file upload endpoint
app.post('/api/files/upload', async (request, reply) => {
try {
const data = await request.file();
if (!data) {
return reply.code(400).send({ error: 'No file uploaded' });
}
// Read file buffer
const buffer = await data.toBuffer();
// Convert buffer to File-like object for uploadFile
const file = new File([buffer], data.filename, {
type: data.mimetype,
});
// Upload file to Filejar
// The body parameter is optional - Filejar will automatically use the file's original name
const result = await filejar.upload.uploadFile([file]);
// Or with explicit file name:
// const result = await filejar.upload.uploadFile([file], {
// body: [{ file_name: data.filename }],
// });
if (!result.response || result.response.length === 0) {
return reply.code(500).send({ error: 'Failed to upload file' });
}
const uploadResult = result.response[0];
const acknowledged = result.acknowledge[0];
// Check if acknowledgment was successful
if ('error' in acknowledged) {
return reply.code(500).send({ error: acknowledged.error });
}
// Construct file URL using the key
const fileUrl = `https://cdn.filejar.dev/${uploadResult.key}`;
// Store file metadata in database
const savedFile = await fileRepo.create({
key: uploadResult.key,
uploadId: uploadResult.upload_id,
originalName: data.filename,
contentType: acknowledged.content_type,
size: acknowledged.size,
url: fileUrl,
uploadedBy: request.user?.id, // Assuming you have auth plugin
});
return reply.send({
success: true,
file: savedFile,
});
} catch (error) {
console.error('Upload error:', error);
if (error instanceof Filejar.APIError) {
return reply.code(error.status || 500).send({
error: error.message,
status: error.status
});
}
return reply.code(500).send({ error: 'Failed to upload file' });
}
});
Multiple Files Upload Endpoint
Create an endpoint to upload multiple files:Copy
// Multiple files upload endpoint
app.post('/api/files/upload-multiple', async (request, reply) => {
try {
const parts = request.parts();
const files: File[] = [];
// Collect all files from multipart form
for await (const part of parts) {
if (part.type === 'file') {
const buffer = await part.toBuffer();
files.push(
new File([buffer], part.filename, {
type: part.mimetype,
})
);
}
}
if (files.length === 0) {
return reply.code(400).send({ error: 'No files uploaded' });
}
// Upload all files to Filejar
// The body parameter is optional - Filejar will automatically use each file's original name
const result = await filejar.upload.uploadFile(files);
// Or with explicit file names:
// const result = await filejar.upload.uploadFile(files, {
// body: files.map(file => ({ file_name: file.name })),
// });
if (!result.response || result.response.length === 0) {
return reply.code(500).send({ error: 'Failed to upload files' });
}
// Store file metadata in database
const filePromises = result.response.map(async (uploadResult, index) => {
const originalFile = files[index];
const acknowledged = result.acknowledge[index];
// Skip if acknowledgment failed
if ('error' in acknowledged) {
console.error(`Failed to acknowledge ${originalFile.name}:`, acknowledged.error);
return null;
}
// Construct file URL using the key
const fileUrl = `https://cdn.filejar.dev/${uploadResult.key}`;
const savedFile = await fileRepo.create({
key: uploadResult.key,
uploadId: uploadResult.upload_id,
originalName: originalFile.name,
contentType: acknowledged.content_type,
size: acknowledged.size,
url: fileUrl,
uploadedBy: request.user?.id,
});
return savedFile;
});
const uploadedFiles = (await Promise.all(filePromises)).filter(file => file !== null);
return reply.send({
success: true,
files: uploadedFiles,
count: uploadedFiles.length,
});
} catch (error) {
console.error('Upload error:', error);
if (error instanceof Filejar.APIError) {
return reply.code(error.status || 500).send({
error: error.message,
status: error.status
});
}
return reply.code(500).send({ error: 'Failed to upload files' });
}
});
Retrieve Files from Database
Create an endpoint to retrieve file information using the stored key:Copy
import { fileRepo } from '@/lib/db-repo';
// Get file by ID
app.get('/api/files/:id', async (request, reply) => {
try {
const { id } = request.params as { id: string };
const file = await fileRepo.findById(id);
if (!file) {
return reply.code(404).send({ error: 'File not found' });
}
return reply.send(file);
} catch (error) {
console.error('Error retrieving file:', error);
return reply.code(500).send({ error: 'Failed to retrieve file' });
}
});
// Get all files
app.get('/api/files', async (request, reply) => {
try {
const files = await fileRepo.findAll();
return reply.send({ files });
} catch (error) {
console.error('Error retrieving files:', error);
return reply.code(500).send({ error: 'Failed to retrieve files' });
}
});
Client-Side Usage
Upload Single File
Copy
// Client-side: Upload single file
async function uploadFile(file: File) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch(`${API_BASE_URL}/api/files/upload`, {
method: 'POST',
body: formData,
});
const data = await response.json();
return data.file; // Contains id, filejarId, filejarKey, name, url
}
Upload Multiple Files
Copy
// Client-side: Upload multiple files
async function uploadFiles(files: File[]) {
const formData = new FormData();
files.forEach(file => {
formData.append('files', file);
});
const response = await fetch(`${API_BASE_URL}/api/files/upload-multiple`, {
method: 'POST',
body: formData,
});
const data = await response.json();
return data.files; // Array of file objects
}
Retrieve File
Simply use the file key to construct the URL:Copy
// Direct URL access using the file key
const fileUrl = `https://cdn.filejar.dev/${key}`;
// Example: Display file in img tag
<img src={`https://cdn.filejar.dev/${fileKey}`} alt="Uploaded file" />
Complete Example
Here’s a complete Fastify server setup with all endpoints:Copy
import Fastify from 'fastify';
import Filejar from 'filejar';
import { fileRepo } from '@/lib/db-repo';
const app = Fastify();
// Initialize Filejar client
const filejar = new Filejar({
apiKey: process.env.FILEJAR_API_KEY,
});
// Register multipart plugin for file uploads
await app.register(import('@fastify/multipart'), {
limits: {
fileSize: 10 * 1024 * 1024, // 10MB
},
});
// Single file upload
app.post('/api/files/upload', async (request, reply) => {
// ... single upload code from above
});
// Multiple files upload
app.post('/api/files/upload-multiple', async (request, reply) => {
// ... multiple upload code from above
});
// Get file by ID
app.get('/api/files/:id', async (request, reply) => {
// ... get file code from above
});
// Get all files
app.get('/api/files', async (request, reply) => {
// ... get all files code from above
});
// Start server
const start = async () => {
try {
await app.listen({ port: 3000 });
console.log('Server running on http://localhost:3000');
} catch (err) {
app.log.error(err);
process.exit(1);
}
};
start();