A comprehensive, secure, and feature-rich Power Apps Component Framework (PCF) control for file uploads to Azure Blob Storage with modern UI, drag-and-drop support, and enterprise-grade security.
- Clean, card-based design with smooth animations and micro-interactions
- Drag-and-drop zone with visual feedback
- Real-time progress tracking with animated progress bars
- Responsive design that works on desktop and mobile
- Accessibility compliant with ARIA labels and keyboard navigation
- Dark/light mode support through CSS variables
- No client-side credentials - eliminates connection string exposure
- SAS token authentication with short-lived, minimal-permission tokens
- Multiple auth modes: SAS from server, direct SAS, or server proxy
- File validation with type and size restrictions
- Rate limiting and abuse protection
- CORS configuration for cross-origin security
- Multi-file support with configurable limits
- File preview with type-specific icons
- Retry mechanism for failed uploads (up to 3 attempts)
- Cancel functionality for in-progress uploads
- Duplicate detection and prevention
- Chunked uploads for large files (>50MB)
- Real upload progress using XMLHttpRequest
- Status indicators (pending, uploading, success, error)
- Toast notifications with auto-dismiss
- Error messages with actionable information
- Success confirmations with file details
- File type restrictions with customizable accepted types
- File size limits with configurable maximums
- Upload modes (single vs multiple files)
- Metadata collection with custom property mapping
- Chunked upload configuration
- Authentication mode selection
- Power Apps Component Framework CLI
- Azure Storage Account
- Azure Function (for SAS token generation - recommended)
- Node.js 16+ and npm
npm installnpm run buildcd azure-function
func azure functionapp publish YourFunctionAppName- Import the solution containing the PCF control
- Add the control to a form or canvas app
- Configure the required properties:
- Storage Account Name: Your Azure Storage account name
- Container Name: Target blob container
- Upload Auth Mode:
SASFromServer(recommended) - SAS Request URL: Your Azure Function endpoint
Upload Auth Mode: SASFromServer
SAS Request URL: https://your-function-app.azurewebsites.net/api/GenerateSasToken
Upload Auth Mode: DirectSASToken
SAS Token: sv=2023-11-03&ss=b&srt=sco&sp=cw&se=2024-01-01T00:00:00Z&...
Upload Auth Mode: ServerProxyUpload
Upload Endpoint: https://your-api.com/upload
Accepted File Types: PDF, Image, Text
Max File Size (MB): 100
Enable Multiple Files: Yes
Max File Count: 10
Enable Chunked Upload: Yes
Chunk Size (MB): 10
Enable Metadata: Yes
User Name Property: UploadedBy
Timestamp Property: UploadedAt
User Email Property: EmailID
customFileUpload/
βββ index.ts # Main control implementation
βββ ControlManifest.Input.xml # Control properties and metadata
βββ css/
β βββ customFileUpload.css # Modern styling with CSS variables
βββ generated/
βββ ManifestTypes.ts # Auto-generated TypeScript types
customFileUpload: Main control classFileUploadItem: File upload state managementSASResponse: SAS token response interfaceNotificationItem: Toast notification interface
- User selects files β Client validates
- Request SAS token β Server validates user permissions
- Receive short-lived SAS β Direct upload to Azure
- Progress tracking β Real-time feedback
- Success/Error handling β User notifications
- New upload mode: OneLake via AAD bearer token (client credentials, shortβlived)
- Direct upload using ADLS Gen2 DFS API (create β append β flush)
- Dynamic per-user subpaths supported
- Chunked uploads (default 8MB) up to 1GB
# Start development server
npm run start
# Start with watch mode
npm run start:watch
# Run linting
npm run lint
# Fix linting issues
npm run lint:fix# Run tests (when implemented)
npm test
# Build for production
npm run build
# Clean build artifacts
npm run clean- Event handlers bound once to prevent memory leaks
- CSS classes instead of inline styles
- TypeScript interfaces for type safety
- Async/await for readable asynchronous code
- Error boundaries for graceful error handling
func init FileUploadSasGenerator --dotnet
func new --name GenerateSasToken --template "Http trigger"{
"IsEncrypted": false,
"Values": {
"AzureStorageConnectionString": "YourConnectionString",
"ContainerName": "uploads",
"MaxFileSizeMB": "100",
"MaxFileCount": "10"
}
}func azure functionapp publish YourFunctionAppNameAdd a function that returns a shortβlived AAD access token for scope https://storage.azure.com/.default:
- Function name:
GenerateOneLakeToken - App settings required:
TenantId,ClientId,ClientSecret - Response shape:
{ "accessToken": "<JWT>", "expiresAt": "2025-01-01T10:00:00Z" }- Use SAS tokens with short expiration (1 hour or less)
- Implement server-side file validation
- Enable Azure Monitor logging
- Use HTTPS for all communications
- Restrict CORS origins
- Implement rate limiting
- Regular security audits
- Store connection strings in client-side code
- Use long-lived SAS tokens
- Skip file type validation
- Ignore error logging
- Disable CORS restrictions
- Allow unlimited file sizes
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
- Mobile browsers (iOS Safari 14+, Android Chrome 90+)
/* Mobile */
@media (max-width: 480px) { ... }
/* Tablet */
@media (max-width: 768px) { ... }
/* Desktop */
@media (min-width: 769px) { ... }The control uses CSS variables for easy theming:
:root {
--primary-color: #0078d4;
--success-color: #28a745;
--error-color: #dc3545;
--border-radius-md: 12px;
--shadow-md: 0 4px 8px rgba(0, 0, 0, 0.12);
}- Lazy loading of file list items
- Event delegation for dynamic content
- Memory management with proper cleanup
- Efficient DOM updates with minimal reflows
- Chunked uploads for large files
- Minified: ~45KB
- Gzipped: ~15KB
- Tree-shakable: Unused code removed
Cause: Invalid or expired SAS token Solution: Check Azure Function and storage permissions
Cause: JavaScript error or CSS issue Solution: Check browser console for errors
Cause: Missing CORS configuration Solution: Configure CORS on Azure Storage and Function
Cause: Request timeout or size limits Solution: Enable chunked uploads
Enable debug logging by setting:
private DEBUG_MODE = true;| Property | Type | Required | Default | Description |
|---|---|---|---|---|
storageAccountName |
string | β | - | Azure Storage account name |
containerName |
string | β | - | Target container name |
uploadAuthMode |
enum | β | SASFromServer | Authentication mode |
sasRequestUrl |
string | β | - | SAS token endpoint |
maxFileSizeMB |
number | β | 100 | Maximum file size |
enableMultiple |
boolean | β | false | Allow multiple files |
oneLakeWorkspaceId |
string | β for OneLake | - | Fabric workspace ID (GUID) |
oneLakeLakehouseId |
string | β for OneLake | - | Fabric lakehouse ID (GUID) |
oneLakeBasePath |
string | β | Files | Root path inside lakehouse |
oneLakeUserSubPath |
string | β | - | Per-user subfolder (optional) |
oneLakeChunkSizeMB |
number | β | 8 | DFS append chunk size |
aadTokenRequestUrl |
string | β for OneLake | - | Endpoint to fetch AAD token |
oneLakeFolderUrl |
string | β for OneLakeDirectToken | - | DFS base folder URL |
aadAccessToken |
string | β for OneLakeDirectToken | - | Bearer token (dev only) |
// Public methods (if exposed)
public uploadFiles(files: File[]): Promise<void>
public cancelAllUploads(): void
public clearFileList(): void// Custom events (if implemented)
onUploadComplete: (files: UploadedFile[]) => void
onUploadError: (error: UploadError) => void
onProgressUpdate: (progress: UploadProgress) => void- Connection string property removed
- New authentication modes added
- CSS classes changed (update custom styles)
- Event handling improved (memory leak fixes)
- Update manifest properties
- Deploy Azure Function for SAS tokens
- Update CSS customizations
- Test authentication flow
- Update error handling
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
- Follow TypeScript best practices
- Use ESLint configuration
- Add accessibility attributes
- Test on multiple browsers
- Document new features
This project is licensed under the MIT License - see the LICENSE file for details.
For support and questions:
- Create an issue in the repository
- Check the troubleshooting guide
- Review the security documentation
- Contact the development team
- Image preview thumbnails
- Folder upload support
- Virus scanning integration
- Advanced file validation
- Upload pause/resume
- Multi-language support
- Custom progress themes
- Advanced analytics
- Bulk operations
- Cloud provider support (AWS, GCP)
Built with β€οΈ for the Power Apps community