Question
How can I create a file-upload feature in an Angular 5 application? I am new to Angular and need a beginner-friendly approach or documentation. I tried using the ng4-files package, but it does not work with Angular 5.
Short Answer
You will learn how browser file inputs work in Angular, how to read the selected File, and how to send it to a server with FormData and Angular's HttpClient. You will also see basic validation, upload progress handling, and a reusable component structure.
Concept
A file upload has two separate jobs:
- Choose a file in the browser using an HTML
<input type="file">element. - Send that file to a server using an HTTP request.
Angular does not need a special package for the basic version. The browser already provides a File object when a user selects a file. Your Angular component stores that object, places it in a FormData instance, and sends the form data to an API endpoint.
FormData is important because files are binary data. It creates a request using multipart/form-data, the standard request format that servers use for form submissions containing files.
In Angular 5, use HttpClient from @angular/common/http. It replaces the older Http service and supports typed responses and upload-progress events.
A successful upload still requires a backend endpoint such as POST /api/uploads. Angular can select and transmit the file, but the server must validate it, store it, and return a response.
Mental Model
Think of the file input as a customer choosing a package at a shipping desk.
- The
<input type="file">lets the customer choose the package. - The browser gives Angular a
Fileobject: the package plus details such as its name, size, and type. FormDatais the shipping box and label.HttpClientis the delivery service that sends the box to the server.- The backend is the warehouse that receives and stores the package.
Selecting a file does not upload it automatically. Uploading happens only when your code sends the HTTP request.
Syntax and Examples
The core flow is:
selectedFile: File | null = null;
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
this.selectedFile = input.files?.[0] ?? null;
}
upload(): void {
if (!this.selectedFile) {
return;
}
const formData = new FormData();
formData.append('file', this.selectedFile, this.selectedFile.name);
this.http.post('/api/uploads', formData).subscribe();
}
Template:
<input type="file" (change)="onFileSelected($event)">
<button type="button" (click)="upload()" [disabled]="!selectedFile">
Upload
</button>
input.files is a FileList, because a file input can potentially contain multiple files. For a single-file upload, use files[0].
The first argument to formData.append() is the field name sent to the server. In this example it is file. Your backend must expect the same field name.
Step by Step Execution
Consider this example:
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
this.selectedFile = input.files?.[0] ?? null;
}
upload(): void {
if (!this.selectedFile) {
this.message = 'Choose a file first.';
return;
}
const data = new FormData();
data.append('file', this.selectedFile, this.selectedFile.name);
this.http.post('/api/uploads', data).subscribe({
next: () => this.message = 'Upload complete.',
error: () => this.message = 'Upload failed.'
});
}
Step by step:
- The user chooses
report.pdfin the file picker. - The browser raises the input's
changeevent. onFileSelectedreceives that event and gets the input element.input.files?.[0]retrieves the first selectedFileobject.- When the user clicks Upload,
upload()checks whether a file was selected. - A new
FormDataobject is created and the file is added under thefilefield name. HttpClient.post()sends the multipart request to/api/uploads.- The subscription handles either the successful response or an error response.
Real World Use Cases
File uploads appear in many applications:
- Profile settings: upload an avatar or company logo.
- Support portals: attach screenshots, logs, or documents to a ticket.
- Content management systems: upload images, PDFs, and downloadable resources.
- Business workflows: submit invoices, receipts, contracts, or spreadsheets.
- Data import tools: upload CSV files for processing.
- Messaging applications: share images and attachments.
In each case, validate both in the browser for user feedback and on the server for security. Client-side checks can be bypassed, so the server is the final authority.
Real Codebase Usage
In production Angular applications, file upload code commonly follows these patterns:
- Keep HTTP calls in a service. Components manage the user interface; an
UploadServicesends requests. - Use guard clauses. Return early when no file is selected or validation fails.
- Validate before uploading. Check size and allowed file types to give fast feedback.
- Show upload state. Disable repeated clicks while uploading and display success or failure messages.
- Track progress for larger files. Send requests with
observe: 'events'andreportProgress: true. - Let the server generate final file names. Do not trust a client-provided filename as a safe storage path.
- Handle errors explicitly. Network failure, unauthorized access, oversized files, and unsupported types all need useful messages.
A service-based upload method can look like this:
upload(file: File) {
const formData = new FormData();
formData.append('file', file, file.name);
return this.http.post('/api/uploads', formData);
}
The component subscribes to that returned observable and updates its view state.
Common Mistakes
Setting the Content-Type header manually
This is a frequent mistake:
// Incorrect for FormData
const headers = new HttpHeaders({
'Content-Type': 'multipart/form-data'
});
this.http.post('/api/uploads', formData, { headers });
Do not manually set Content-Type when sending FormData. The browser adds multipart/form-data plus a required boundary value. Set no content-type header unless your API has another specific requirement.
Sending the input value instead of the file
// Incorrect: this is usually a browser-protected path-like string, not file data.
const value = (event.target as HTMLInputElement).value;
Use input.files?.[0], which is the actual File object.
Forgetting to import HttpClientModule
Without this import, Angular cannot inject HttpClient:
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [HttpClientModule]
})
export class AppModule {}
Assuming selection means upload
The (change) handler only stores the selected file. Call an HTTP method to upload it.
Trusting only the browser validation
Checks such as file.type === 'image/png' improve the experience but do not secure your system. Validate file type, size, permissions, and file contents on the server too.
Mismatching the form field name
If Angular sends formData.append('file', file) but the server expects avatar, the server may report that no file was received. Keep the names consistent.
Comparisons
| Approach | Best for | Notes |
|---|---|---|
Native file input + FormData | Most standard uploads | No external upload library required. |
Angular HttpClient | Angular 5 applications | Supports observables, errors, and progress events. |
Older Angular Http service | Legacy code only | Avoid for new Angular 5 code; HttpClient is preferred. |
| Uploading on file selection | Quick, immediate uploads | Start the request inside the change handler. |
| Uploading after a button click | Forms and confirmation flows | Lets the user review or replace the file first. |
| Single-file input | Avatar or one document | Read files[0]. |
| Multiple-file input | Galleries and bulk attachments | Add multiple and loop through input.files. |
For a multiple-file input:
<input type="file" multiple (change)="onFilesSelected($event)">
const input = event.target as HTMLInputElement;
const files = Array.from(input.files ?? []);
const formData = new FormData();
files.forEach(file => formData.append('files', file, file.name));
Cheat Sheet
// Read one selected file
const input = event.target as HTMLInputElement;
const file = input.files?.[0] ?? null;
// Build multipart form data
const data = new FormData();
data.append('file', file, file.name);
// Send it
this.http.post('/api/uploads', data).subscribe();
- Use
<input type="file">to open the browser file picker. - Read selected files from
input.files, notinput.value. - Use
FormDatafor file requests. - The
append()field name must match what the server expects. - Import
HttpClientModuleonce in the Angular module. - Do not manually set
Content-TypeforFormData. - Use
accept="image/*"as a helpful UI hint, not as security. - Validate uploads on the server even if the client validates them.
- For many files, use
multipleand iterate overFileList.
FAQ
Does Angular 5 have a built-in file upload component?
Angular uses the browser's standard <input type="file">. You build the upload behavior by sending the chosen File with HttpClient and FormData.
Do I need an external Angular file upload library?
Not for standard uploads. A library can help with drag-and-drop, queues, retries, or advanced UI, but native browser APIs are enough for basic uploads.
Why is my backend receiving no file?
Check that you append the file to FormData, that the field name matches the backend expectation, and that you do not manually override the multipart Content-Type header.
Can I upload multiple files in Angular?
Yes. Add multiple to the input, convert input.files to an array, and append each file to FormData.
How do I restrict uploads to images?
Use accept="image/*" on the input and validate the selected file in TypeScript. Also enforce image validation on the server.
Can I show upload progress with Angular HttpClient?
Yes. Send the request with reportProgress: true and observe: 'events', then calculate a percentage from HttpEventType.UploadProgress events.
Is client-side file validation secure?
No. It only improves the user experience. The server must enforce all security and storage rules.
Mini Project
Description
Build a small profile-image uploader. The user selects an image, sees its name, and uploads it to an API endpoint. The component validates the file before sending it and reports the result.
Goal
Create an Angular 5 component that uploads one PNG or JPEG image smaller than 2 MB.
Requirements
Use a native file input that accepts images only.
Store the selected file and display its name.
Reject files that are not PNG or JPEG images.
Reject files larger than 2 MB.
Send valid files to POST /api/profile-image with FormData.
Show success or error feedback.
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Accessing Input Value from EventTarget in TypeScript
Learn why EventTarget has no value property in TypeScript and safely read values from HTML input events in Angular applications.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.