Get Linked File Meta Handler
This page provides complete examples for implementing the Get Linked File Meta backend handler. The getlinkedfilemetaevent endpoint retrieves file metadata (name, size, MIME type) without downloading the actual file content.
What is Get Linked File Meta?
getlinkedfilemetaevent is the backend endpoint that:
- Receives a file identifier
- Retrieves file metadata from storage
- Returns file name, size, and MIME type
- Does NOT download the file content (fast and lightweight)
Complete Get Linked File Meta Implementation
Choose your backend language:
- C# / .NET
- PHP
Controllers/FormsPublicController.cs
public class LinkedFileRequestDto
{
public string FileId { get; set; }
}
[HttpPost("getlinkedfilemetaevent")]
[AllowAnonymous]
public async Task<IActionResult> GetLinkedFileMeta([FromBody] LinkedFileRequestDto request)
{
string tenantId = GetCurrentTenantId();
string fileName = string.Empty;
long fileSize = 0;
string fileMimetype = "application/octet-stream";
var fileStorageService = GetFileStorageService();
if (fileStorageService == null)
throw new InvalidOperationException("File storage provider not configured.");
if (!string.IsNullOrEmpty(request.FileId))
{
// Parse file identifier (format: "bucket-name:path/to/file.pdf")
string[] parts = request.FileId.Split(':');
string bucketName = parts[0];
string filePath = parts[1];
// Extract filename from path
fileName = Path.GetFileName(filePath);
// Get metadata from storage (lightweight operation)
var metadata = await fileStorageService.GetFileMetadataAsync(
tenantId,
filePath,
bucketName
);
fileSize = metadata?.ContentLength ?? 0;
fileMimetype = GetMimeType(filePath);
}
// Build response
var response = new HandlerResponse();
response.Set(HandlerResponse.LinkedFileName, fileName);
response.Set(HandlerResponse.LinkedFileSize, fileSize);
response.Set(HandlerResponse.LinkedFileMimetype, fileMimetype);
return Ok(await response.Get());
}
private string GetMimeType(string fileName)
{
var extension = Path.GetExtension(fileName).ToLowerInvariant();
return extension switch
{
".pdf" => "application/pdf",
".jpg" or ".jpeg" => "image/jpeg",
".png" => "image/png",
".gif" => "image/gif",
".doc" => "application/msword",
".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".xls" => "application/vnd.ms-excel",
".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".zip" => "application/zip",
".txt" => "text/plain",
".mp4" => "video/mp4",
".mp3" => "audio/mpeg",
_ => "application/octet-stream"
};
}
controllers/FormsPublicController.php
<?php
class FormsPublicController {
public function getLinkedFileMeta(Request $request) {
$fileId = $request->input('fileId');
if (empty($fileId)) {
return response()->json(['error' => 'File ID is required'], 400);
}
$tenantId = $this->getCurrentTenantId();
$fileStorageService = $this->getFileStorageService();
if (!$fileStorageService) {
throw new Exception('File storage provider not configured.');
}
$fileName = '';
$fileSize = 0;
$fileMimetype = 'application/octet-stream';
// Parse file identifier (format: "bucket-name:path/to/file.pdf")
$parts = explode(':', $fileId, 2);
if (count($parts) === 2) {
$bucketName = $parts[0];
$filePath = $parts[1];
try {
// Extract filename from path
$fileName = basename($filePath);
// Get metadata from storage (lightweight operation)
$metadata = $fileStorageService->getFileMetadata(
$tenantId,
$filePath,
$bucketName
);
$fileSize = $metadata['ContentLength'] ?? 0;
$fileMimetype = $this->getMimeType($filePath);
}
catch (Exception $e) {
Log::error("Failed to get file metadata: {$e->getMessage()}");
return response()->json(['error' => 'File not found'], 404);
}
}
return response()->json([
'linkedFileName' => $fileName,
'linkedFileSize' => $fileSize,
'linkedFileMimetype' => $fileMimetype
]);
}
private function getMimeType($fileName) {
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
$mimeTypes = [
'pdf' => 'application/pdf',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'xls' => 'application/vnd.ms-excel',
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'zip' => 'application/zip',
'txt' => 'text/plain',
'mp4' => 'video/mp4',
'mp3' => 'audio/mpeg'
];
return $mimeTypes[$extension] ?? 'application/octet-stream';
}
private function getCurrentTenantId() {
return session('tenant_id') ?? 'default';
}
private function getFileStorageService() {
return app('file.storage');
}
}
?>
Request Structure
{
"fileId": "bucket-name:tenant/forms/2026/01/27/document.pdf"
}
Key Fields:
- fileId - The file identifier returned from the upload endpoint
Response Structure
{
"linkedFileName": "document.pdf",
"linkedFileSize": 1048576,
"linkedFileMimetype": "application/pdf"
}
Response Fields:
- linkedFileName - The file name without path
- linkedFileSize - File size in bytes
- linkedFileMimetype - The MIME type of the file
Storage Implementation Examples
S3 Storage Metadata
C# - Get File Metadata from S3
public async Task<GetObjectMetadataResponse> GetFileMetadataFromS3(
string tenantId,
string filePath,
string bucketName)
{
var s3Client = new AmazonS3Client(/* credentials */);
var metadataRequest = new GetObjectMetadataRequest
{
BucketName = bucketName,
Key = filePath
};
return await s3Client.GetObjectMetadataAsync(metadataRequest);
}
Local File Storage Metadata
C# - Get File Metadata from Local Storage
public Task<FileMetadata> GetFileMetadataFromLocal(
string tenantId,
string filePath,
string bucketName)
{
var fullPath = Path.Combine(_uploadDirectory, bucketName, filePath);
if (!File.Exists(fullPath))
throw new FileNotFoundException("File not found", fullPath);
var fileInfo = new FileInfo(fullPath);
return Task.FromResult(new FileMetadata
{
ContentLength = fileInfo.Length,
LastModified = fileInfo.LastWriteTimeUtc,
ETag = ComputeETag(fullPath)
});
}
Azure Blob Storage Metadata
C# - Get File Metadata from Azure Blob
public async Task<BlobProperties> GetFileMetadataFromAzure(
string tenantId,
string filePath,
string containerName)
{
var blobClient = new BlobContainerClient(
_connectionString,
containerName
);
var blob = blobClient.GetBlobClient(filePath);
if (!await blob.ExistsAsync())
throw new FileNotFoundException("Blob not found", filePath);
var properties = await blob.GetPropertiesAsync();
return properties.Value;
}
Use Cases
Display File Information
Show file details without downloading:
TypeScript - Display File Information
async function displayFileInfo(fileId: string) {
const response = await fetch('/your-api-path/getlinkedfilemetaevent', {
method: 'POST',
body: JSON.stringify({ fileId }),
headers: { 'Content-Type': 'application/json' }
});
const meta = await response.json();
console.log(`File: ${meta.linkedFileName}`);
console.log(`Size: ${formatBytes(meta.linkedFileSize)}`);
console.log(`Type: ${meta.linkedFileMimetype}`);
}
function formatBytes(bytes: number): string {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
}
Validate File Size Before Download
Check if file is too large before attempting download:
TypeScript - Validate File Size Before Download
async function downloadIfNotTooLarge(fileId: string, maxSizeMB: number) {
const meta = await getFileMeta(fileId);
const maxBytes = maxSizeMB * 1024 * 1024;
if (meta.linkedFileSize > maxBytes) {
alert(`File is too large (${formatBytes(meta.linkedFileSize)}). Maximum is ${maxSizeMB}MB.`);
return;
}
// Proceed with download
await downloadFile(fileId);
}
Show File Icons
Display appropriate icons based on file type:
TypeScript - Get File Icon by MIME Type
function getFileIcon(mimeType: string): string {
const iconMap: Record<string, string> = {
'application/pdf': 'pdf-icon.svg',
'image/jpeg': 'image-icon.svg',
'image/png': 'image-icon.svg',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'word-icon.svg',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'excel-icon.svg'
};
return iconMap[mimeType] || 'file-icon.svg';
}
Performance Benefits
Lightweight Operation
Getting metadata is much faster than downloading the file:
Full File Download: ~500ms for 10MB file
Metadata Only: ~50ms for same file
Cache Metadata
Cache file metadata to avoid repeated requests:
C# - Cache File Metadata
private readonly IMemoryCache _cache;
public async Task<FileMetadata> GetFileMetadataWithCache(string fileId)
{
var cacheKey = $"file-meta:{fileId}";
if (_cache.TryGetValue(cacheKey, out FileMetadata cached))
{
return cached;
}
var metadata = await GetFileMetadataFromStorage(fileId);
_cache.Set(cacheKey, metadata, TimeSpan.FromMinutes(15));
return metadata;
}
Error Handling
C# - Handle Errors
public async Task<IActionResult> GetLinkedFileMeta([FromBody] LinkedFileRequestDto request)
{
try
{
if (string.IsNullOrEmpty(request.FileId))
{
return BadRequest(new {
error = "File ID is required"
});
}
// Check authorization
if (!await CanUserAccessFile(GetCurrentUserId(), request.FileId))
{
return Unauthorized(new {
error = "Access denied"
});
}
// Get metadata
var metadata = await GetFileMetadata(request.FileId);
if (metadata == null)
{
return NotFound(new {
error = "File not found"
});
}
return Ok(new {
linkedFileName = metadata.FileName,
linkedFileSize = metadata.Size,
linkedFileMimetype = metadata.MimeType
});
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving file metadata");
return StatusCode(500, new {
error = "Failed to retrieve file metadata"
});
}
}
Next Steps
- Get Linked File Handler - Download file as Base64
- Get Linked File By Chunks - Handle large files
- Download File Handler - Direct file downloads