How to implement file upload functionality with Edge Functions

This guide demonstrates how to implement secure file upload functionality using Azion Edge Functions and Edge Storage. By handling file uploads at the edge, you can provide faster upload speeds and better user experience while maintaining security and scalability.

Requirements

Before you begin, ensure you have:

Code

This is a code example of how to use Edge Functions with Edge Storage to implement a file upload functionality. The complete code example you can find in this GitHub repository.

import type { AzionBucketObject, AzionStorageResponse } from "azion/storage";
import { createObject } from "azion/storage";
import { Hono } from "hono";
import { fire } from "hono/service-worker";
const app = new Hono();
app.post("/upload", async (c) => {
const body = await c.req.parseBody();
const file = body["file"]; // File | string
// First check if file is a valid File object
if (
!file ||
typeof file !== "object" ||
typeof file.arrayBuffer !== "function"
) {
return c.json({ message: "Invalid file" }, 400);
}
// Check if file size exceeds 2MB limit
const maxSize = 2 * 1024 * 1024; // 2MB
if (file.size > maxSize) {
return c.json({ message: "File size exceeds 2MB limit" }, 413);
}
try {
const { data: newObject, error }: AzionStorageResponse<AzionBucketObject> =
await createObject({
bucket: process.env.BUCKET_NAME!,
key: file.name,
// @ts-expect-error content is wrongly typed
content: await file.arrayBuffer(),
});
if (error) {
throw new Error(error.message);
}
if (newObject) {
console.log(`Object created with key: ${newObject.key}`);
} else {
console.error("Failed to create object", error);
}
// @ts-expect-error content is wrongly typed
const content = new Uint8Array(newObject.content);
return c.body(content, {
status: 200,
headers: {
"Content-Type": file.type,
"Content-Disposition": `attachment; filename="${newObject?.key}"`,
"Content-Length": newObject?.size?.toString() ?? "0",
},
});
} catch (error) {
console.error("Error uploading file:", error);
return c.json({ message: "Error uploading file" }, 500);
}
});
fire(app);

Deploying to Azion

Step 1: Authenticate with Azion

  1. Log in to your Azion account via CLI:
Terminal window
azion login
  1. Follow the authentication prompts to connect your CLI with your Azion account.

Step 2: Deploy the Edge Function

Deploy your file upload application to Azion’s edge network:

Terminal window
azion deploy

The deployment process will:

  • Upload your Edge Function code
  • Configure the edge application
  • Set up the necessary routing rules
  • Configure storage permissions
  • Provide you with a unique domain

Step 3: Configure storage permissions

  1. Access Azion Console > Edge Storage
  2. Select your storage bucket
  3. Configure appropriate permissions for your Edge Function to read/write files

Step 4: Access your application

After deployment, you’ll receive a domain like https://xxxxxxx.map.azionedge.net. Your file upload application will be available at this URL within a few minutes after DNS propagation.

Understanding the implementation

File upload process

The file upload Edge Function typically handles:

  1. Request validation: Checking file types, sizes, and security
  2. Multipart form parsing: Processing multipart/form-data requests
  3. File processing: Validating and preparing files for storage
  4. Storage upload: Saving files to Edge Storage
  5. Response generation: Returning upload status and file information

Security considerations

  • File type validation: Only allow specific file types
  • Size limits: Enforce maximum file size restrictions
  • Virus scanning: Implement malware detection when possible
  • Access control: Validate user permissions before uploads
  • Input sanitization: Clean file names and metadata

Key benefits

  • Performance: Upload processing at the edge reduces latency
  • Scalability: Automatically scales with demand
  • Global reach: Edge locations provide worldwide coverage
  • Cost efficiency: Optimized data transfer and storage costs

Testing your file upload application

Step 1: Test file upload functionality

  1. Navigate to your deployed application
  2. Use the upload form to test various file types
  3. Verify files are successfully stored in your Edge Storage bucket
  4. Test file size limits and type restrictions

Step 2: Test security features

  1. File type validation: Try uploading restricted file types
  2. Size limits: Test with files exceeding your size limit
  3. Malicious files: Test with files containing suspicious content
  4. Path traversal: Verify file name sanitization

Step 3: Performance testing

  1. Upload speed: Test with various file sizes
  2. Concurrent uploads: Test multiple simultaneous uploads
  3. Error handling: Test network interruptions and failures

Common use cases

  • Document management: Upload and store business documents
  • Image galleries: Handle photo and image uploads
  • Media content: Process video and audio file uploads
  • Form attachments: Handle file attachments in web forms
  • Data import: Process CSV and data file uploads

Troubleshooting

Common issues and solutions

  • Upload failures: Check file size limits and allowed types
  • Storage errors: Verify bucket permissions and configuration
  • Performance issues: Optimize file processing and storage operations
  • Security concerns: Review file validation and sanitization logic

Error handling best practices

  1. Clear error messages: Provide specific feedback to users
  2. Logging: Implement comprehensive error logging
  3. Retry mechanisms: Handle temporary failures efficiently
  4. Progress indicators: Show upload progress for large files

Advanced features

Implementing file processing

You can extend the basic upload functionality with:

  • Image resizing: Automatically resize uploaded images
  • Format conversion: Convert files to different formats
  • Metadata extraction: Extract and store file metadata
  • Thumbnail generation: Create preview images

Adding authentication

Implement user authentication to secure file uploads:

// Example authentication check
function authenticateUser(request) {
const authHeader = request.headers.get('Authorization');
// Implement your authentication logic
return validateToken(authHeader);
}

Next steps

  • Explore advanced file processing techniques
  • Implement file deletion and management features
  • Add user authentication and authorization
  • Integrate with other Azion products like Edge Cache
  • Monitor upload performance and optimize accordingly