Skip to content

Commit

Permalink
update az client to get size and url and save metadata to local json
Browse files Browse the repository at this point in the history
  • Loading branch information
lambley committed Aug 8, 2024
1 parent 5ad69bc commit e386030
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 25 deletions.
15 changes: 14 additions & 1 deletion server/src/routes/deleteRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import express from 'express';
import azureBlobService from '../utils/azureClient';
import { loadFilesData, saveFilesData } from '../utils/fileUtils';
import { FileMetadata } from '../../types/files';
import fs from 'fs';
import path from 'path';

const router = express.Router();

let files: FileMetadata[] = loadFilesData();
const filesDataPath = path.join(__dirname, '../filesData.json');

router.delete('/:key', async (req, res) => {
const fileKey = req.params.key as string;
Expand All @@ -17,10 +19,21 @@ router.delete('/:key', async (req, res) => {
throw new Error('Container client not initialized.');
}

// Delete the file from Azure Blob Storage
const blockBlobClient = containerClient.getBlockBlobClient(fileKey);
await blockBlobClient.delete();

// Load existing files metadata
let files: FileMetadata[] = [];

if (fs.existsSync(filesDataPath)) {
files = loadFilesData();
}

// Remove the deleted file's metadata
files = files.filter((file: FileMetadata) => file.key !== fileKey);

// Save updated metadata to JSON file
saveFilesData(files);

res.status(200).send('File deleted successfully.');
Expand Down
59 changes: 47 additions & 12 deletions server/src/routes/filesRoutes.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,59 @@
import express from 'express';
import fs from 'fs';
import path from 'path';
import { FileMetadata } from '../../types/files';
import azureBlobService from '../utils/azureClient';
import { loadFilesData } from '../utils/fileUtils';

const router = express.Router();

const filesDataPath = path.join(__dirname, '../filesData.json');
// Function to list files in Azure Blob Storage
const listFilesInAzureBlob = async (): Promise<FileMetadata[]> => {
const files: FileMetadata[] = [];

const loadFilesData = (): FileMetadata[] => {
if (fs.existsSync(filesDataPath)) {
const data = fs.readFileSync(filesDataPath);
return JSON.parse(data.toString()) as FileMetadata[];
try {
const containerClient = azureBlobService.getContainerClient();

if (containerClient) {
// List all blobs in the container
const blobIterator = containerClient.listBlobsFlat();

for await (const blob of blobIterator) {
const fileMetadata: FileMetadata = {
name: blob.name,
key: blob.name,
url: `${containerClient.url}/${blob.name}`,
size: blob.properties.contentLength,
};

files.push(fileMetadata);
}
} else {
throw new Error('Azure Blob Service client is not initialized.');
}
} catch (error) {
console.error('Error retrieving files from Azure Blob Storage:', error);
throw error;
}
return [];
};

const files: FileMetadata[] = loadFilesData();
return files;
};

router.get('/', (req, res) => {
res.json(files);
// Endpoint to get files
router.get('/', async (_req, res) => {
let files: FileMetadata[];
try {
if (azureBlobService.getContainerClient()) {
// Attempt to retrieve files from Azure Blob Storage
files = await listFilesInAzureBlob();
} else {
console.log('Azure Blob Service not initialized. Using local JSON backup.');
// Use local JSON backup if Azure Blob Service is not initialized
files = loadFilesData();
}
res.json(files);
} catch (error) {
console.error('Error handling request:', error);
res.status(500).send('Internal Server Error');
}
});

export default router;
20 changes: 16 additions & 4 deletions server/src/routes/uploadRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import { FileMetadata } from '../../types/files';
const router = express.Router();
const upload = multer({ dest: 'uploads/' });

const files: FileMetadata[] = loadFilesData();

router.post('/', upload.single('file'), async (req, res) => {
const fileName = req.body.note as string;
if (!fileName) {
Expand All @@ -24,13 +22,27 @@ router.post('/', upload.single('file'), async (req, res) => {
throw new Error('Container client not initialized.');
}

const blobName = req.file.filename;
const blobName = fileName;
const blockBlobClient = containerClient.getBlockBlobClient(blobName);

await blockBlobClient.uploadFile(req.file.path);
fs.unlinkSync(req.file.path);

files.push({ name: fileName, key: blobName });
// Create new file metadata
const newFileMetadata: FileMetadata = {
name: fileName,
key: blobName,
url: `${containerClient.url}/${blobName}`,
size: req.file.size,
};

// Load existing files metadata
const files = loadFilesData();

// Update metadata
files.push(newFileMetadata);

// Save updated metadata to JSON file
saveFilesData(files);

res.status(200).send('File uploaded successfully.');
Expand Down
24 changes: 16 additions & 8 deletions server/src/utils/azureClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,24 @@ class AzureBlobService {
private containerName: string;

constructor(
accountName: string = process.env.AZURE_STORAGE_ACCOUNT_NAME!,
accountKey: string = process.env.AZURE_STORAGE_ACCOUNT_KEY!,
containerName: string = process.env.AZURE_CONTAINER_NAME!,
accountName: string = process.env.AZURE_STORAGE_ACCOUNT_NAME || '',
accountKey: string = process.env.AZURE_STORAGE_ACCOUNT_KEY || '',
containerName: string = process.env.AZURE_CONTAINER_NAME || '',
) {
this.accountName = accountName;
this.accountKey = accountKey;
this.containerName = containerName;
}

public async initialize() {
public async initialize(): Promise<void> {
// Check if environment variables are set
if (!this.accountName || !this.accountKey || !this.containerName) {
console.error('Azure Blob Service credentials are missing.');
this.blobServiceClient = null;
this.containerClient = null;
return;
}

try {
const sharedKeyCredential = new StorageSharedKeyCredential(this.accountName, this.accountKey);

Expand All @@ -38,11 +46,11 @@ class AzureBlobService {
console.error('Failed to initialize Azure client:', error);
this.blobServiceClient = null;
this.containerClient = null;
throw error;
throw new Error('Azure Blob Service initialization failed.');
}
}

private async listContainers() {
private async listContainers(): Promise<void> {
try {
if (this.blobServiceClient) {
const iter = this.blobServiceClient.listContainers();
Expand All @@ -52,7 +60,7 @@ class AzureBlobService {
}
} catch (error) {
console.error('Error validating Azure connection:', error);
throw error;
throw new Error('Error validating Azure connection.');
}
}

Expand All @@ -67,7 +75,7 @@ class AzureBlobService {

const azureBlobService = new AzureBlobService();
azureBlobService.initialize().catch((error) => {
console.error('Azure client initialization error:', error);
console.error('Azure client initialization error:', error.message);
});

export default azureBlobService;
3 changes: 3 additions & 0 deletions server/types/files.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Note: key and name are the same. This is an artefact of a previous AWS implementation
interface FileMetadata {
name: string;
key: string;
size?: number;
url?: string;
}

export type { FileMetadata };

0 comments on commit e386030

Please sign in to comment.