Introduction
In modern web applications, file uploads are a common feature — whether it’s invoices, employee documents, or product images.
But every file upload carries a security risk. A single malicious file can compromise your entire system.
That’s why integrating virus scanning during the file upload process is not optional anymore — it’s essential.
In this article, we’ll explore how to build a secure file upload system using Angular (frontend) and ASP.NET Core (backend) with ClamAV or an external antivirus scanning API to detect threats before storing files.
Why File Scanning Matters
Malicious users often upload:
Executable files disguised as PDFs or images
Files containing embedded malware or scripts
Corrupted data that crashes backend processing
If these files are stored unchecked, they can cause:
System compromise
Data corruption
Application downtime
By integrating ClamAV or a cloud-based virus scanning API, you ensure each file is verified before it reaches your database or file server.
System Architecture
Here’s how the process works step by step:
Angular File Upload Component
│
▼
ASP.NET Core File Upload API
│
▼
Virus Scanner (ClamAV / External API)
│
├── Clean → Store File (Database / Cloud / File System)
└── Infected → Reject File & Log Event
Core Components
Angular Frontend: Captures and uploads files.
ASP.NET Core API: Receives and streams the file securely.
ClamAV (or API): Scans uploaded files in real-time.
Storage Layer: Saves only clean files to disk or cloud.
Step 1: File Upload in Angular
A simple Angular component for file upload:
@Component({
selector: 'app-file-upload',
template: `
<h3>Upload File</h3>
<input type="file" (change)="onFileSelected($event)" />
`
})
export class FileUploadComponent {
constructor(private http: HttpClient) {}
onFileSelected(event: any) {
const file = event.target.files[0];
if (file) {
const formData = new FormData();
formData.append('file', file);
this.http.post('https://yourapi.com/api/files/upload', formData)
.subscribe({
next: res => alert('File uploaded successfully!'),
error: err => alert('Upload failed: ' + err.message)
});
}
}
}
Step 2: File Upload API in ASP.NET Core
Create a secure upload endpoint that temporarily stores and scans the file.
[ApiController]
[Route("api/files")]
public class FileUploadController : ControllerBase
{
private readonly IVirusScannerService _virusScanner;
public FileUploadController(IVirusScannerService virusScanner)
{
_virusScanner = virusScanner;
}
[HttpPost("upload")]
public async Task<IActionResult> UploadFile(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("Invalid file");
var tempPath = Path.Combine(Path.GetTempPath(), file.FileName);
using (var stream = new FileStream(tempPath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
var isClean = await _virusScanner.ScanFileAsync(tempPath);
if (!isClean)
{
System.IO.File.Delete(tempPath);
return BadRequest("Virus detected! Upload rejected.");
}
// Move to permanent storage
var finalPath = Path.Combine("C:\\Uploads", file.FileName);
System.IO.File.Move(tempPath, finalPath);
return Ok("File uploaded and scanned successfully.");
}
}
Step 3: Implementing Virus Scanning Service
Option 1: Using ClamAV (Local or Docker Instance)
ClamAV can run as a daemon (clamd) or via TCP.
Here’s an example using TCP scanning:
public class ClamAVVirusScanner : IVirusScannerService
{
private readonly string _clamAVServer;
private readonly int _clamAVPort;
public ClamAVVirusScanner(IConfiguration config)
{
_clamAVServer = config["ClamAV:Server"];
_clamAVPort = int.Parse(config["ClamAV:Port"]);
}
public async Task<bool> ScanFileAsync(string filePath)
{
using (var client = new TcpClient(_clamAVServer, _clamAVPort))
using (var stream = client.GetStream())
{
var fileData = await File.ReadAllBytesAsync(filePath);
var command = Encoding.UTF8.GetBytes("zINSTREAM\0");
await stream.WriteAsync(command, 0, command.Length);
await stream.WriteAsync(fileData, 0, fileData.Length);
// End of stream
await stream.WriteAsync(new byte[] { 0, 0, 0, 0 });
byte[] responseBuffer = new byte[1024];
int bytesRead = await stream.ReadAsync(responseBuffer);
var response = Encoding.UTF8.GetString(responseBuffer, 0, bytesRead);
return !response.Contains("FOUND");
}
}
}
Option 2: Using External Virus Scanning API
If you prefer cloud scanning (no setup required), you can use services like:
VirusTotal API
Cloudmersive Virus Scan
Metadefender API
Example (VirusTotal)
public async Task<bool> ScanWithVirusTotalAsync(string filePath)
{
using var http = new HttpClient();
using var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(await File.ReadAllBytesAsync(filePath)), "file", Path.GetFileName(filePath));
http.DefaultRequestHeaders.Add("x-apikey", "YOUR_API_KEY");
var response = await http.PostAsync("https://www.virustotal.com/api/v3/files", form);
var content = await response.Content.ReadAsStringAsync();
return !content.Contains("\"malicious\"");
}
Step 4: Security Best Practices
Always validate file type before upload.
Set max upload size in ASP.NET Core configuration.
Use random filenames to prevent path traversal.
Never execute or render uploaded files directly.
Log scan results and notify admins of any infected uploads.
Flowchart: File Upload + Virus Scanning Workflow
User Uploads File (Angular)
│
▼
ASP.NET Core API Receives File
│
▼
Temporary Storage (File System / Memory)
│
▼
Virus Scanning (ClamAV or External API)
│
├── Clean → Move to Final Storage
└── Infected → Delete File + Log Event
Advanced Enhancements
Asynchronous Scan Queue: Use background jobs to scan large files in parallel.
Cloud Integration: Upload to Azure Blob or AWS S3 after scan.
Dashboard View: Show scan history and infection statistics.
Alerting System: Notify admin via email or Teams on detection.
Conclusion
A robust file upload pipeline with virus scanning not only improves security but also builds user trust.
By combining Angular, ASP.NET Core, and ClamAV (or any external API), you can easily implement a real-time scanning layer that keeps your ERP, CMS, or document portal safe from threats — without compromising user experience.
Security doesn’t have to slow you down — it can be seamlessly built into your system.