I'm a beginner with Angular, I want to know how to create Angular 5 File upload part, I'm trying to find any tutorial or doc, but I don't see anything anywhere. Any idea for this? And I tried ng4-files but it's not working for Angular 5
-
4so do u want drag and drop or simple `Choose File` btn upload ? Bdw in both cases u simply upload using [FormData](https://developer.mozilla.org/en/docs/Web/API/FormData) – Dhyey Dec 22 '17 at 05:25
-
4Take a look at primeng, I've been using it for a while and it works with angular v5. https://www.primefaces.org/primeng/#/fileupload – Bunyamin Coskuner Dec 22 '17 at 05:45
-
For those who just need to upload JSON to the client, check out this question: https://stackoverflow.com/questions/54971238/upload-json-file-using-angular-6 – AnthonyW May 03 '19 at 14:20
15 Answers
Here is a working example for file upload to api:
Step 1: HTML Template (file-upload.component.html)
Define simple input tag of type file
. Add a function to (change)
-event for handling choosing files.
<div class="form-group">
<label for="file">Choose File</label>
<input type="file"
id="file"
(change)="handleFileInput($event.target.files)">
</div>
Step 2: Upload Handling in TypeScript (file-upload.component.ts)
Define a default variable for selected file.
fileToUpload: File | null = null;
Create function which you use in (change)
-event of your file input tag:
handleFileInput(files: FileList) {
this.fileToUpload = files.item(0);
}
If you want to handle multifile selection, than you can iterate through this files array.
Now create file upload function by calling you file-upload.service:
uploadFileToActivity() {
this.fileUploadService.postFile(this.fileToUpload).subscribe(data => {
// do something, if upload success
}, error => {
console.log(error);
});
}
Step 3: File-Upload Service (file-upload.service.ts)
By uploading a file via POST-method you should use FormData
, because so you can add file to http request.
postFile(fileToUpload: File): Observable<boolean> {
const endpoint = 'your-destination-url';
const formData: FormData = new FormData();
formData.append('fileKey', fileToUpload, fileToUpload.name);
return this.httpClient
.post(endpoint, formData, { headers: yourHeadersConfig })
.map(() => { return true; })
.catch((e) => this.handleError(e));
}
So, This is very simple working example, which I use everyday in my work.

- 10,288
- 6
- 68
- 99

- 11,488
- 5
- 25
- 37
-
2@GregorDoroschenko I was trying to use a model with additional information about the file and I had to do this to get it to work: `const invFormData: FormData = new FormData(); invFormData.append('invoiceAttachment', invoiceAttachment, invoiceAttachment.name); invFormData.append('invoiceInfo', JSON.stringify(invoiceInfo));` The controller has two corresponding parameters, but I had to parse the JSON in the controller. My Core 2 controller wouldn't automatically pickup the model in the parameter. My original design was a model with a file property, but I couldn't get it to work – Papa Stahl Mar 28 '18 at 21:04
-
1@GregorDoroschenko I tried this code `createContrat(fileToUpload: File, newContrat: Contrat): Observable
{ let headers = new Headers(); const endpoint = Api.getUrl(Api.URLS.createContrat)); const formData: FormData =new FormData(); formData.append('fileKey', fileToUpload, FileToUpload.name); let body newContrat.gup(this.auth.getCurrentUser().token); return this.http .post(endpoint, formData, body) .map(() => { return true; }) }` – OnnaB Apr 26 '18 at 14:40 -
1@GregorDoroschenko And for me doesn't work. I post in ws:`Content-Disposition: form-data; name="fileKey"; filename="file.docx" Content-Type: application/octet-stream
` – OnnaB Apr 26 '18 at 14:42 -
1@OnnaB If you are using FormData for file and for other properties, then you should parse your file and other properties as FormData. You can't use FormData and body at the same time. – Gregor Doroschenko Apr 26 '18 at 15:01
-
1
-
1Any way to ensure safe file upload to avoid malicious file uploads since a user can change the extension of the file to disguise the file to other format say .png? – Sushmit Sagar Oct 18 '18 at 17:41
-
2
-
1@imans77 Which error do you have? Send me a link to your code on GitHub or Stackblitz. – Gregor Doroschenko Nov 25 '18 at 07:44
-
1@GregorDoroschenko there isn't any error. It's just that the formData is empty when I set a breakpoint on that, though the file contains the file's information. And in server also there's no data received. It's a key with empty value :-? – imans77 Nov 25 '18 at 14:59
-
1@GregorDoroschenko See the below answer about Angular 5.2.11 thing. That worked for me but the data isn't sent in `request.files` or `request.form` in my flask server, it's in `request.data`, which I still doubt whether it's a correct way of sending file or not :-? – imans77 Nov 25 '18 at 15:02
-
1@imans77 For using FormData, you should set content type to multipart/form-data in the header settings of request. Maybe it's the reason for empty value of key. – Gregor Doroschenko Nov 25 '18 at 15:17
-
1@GregorDoroschenko yeah I also did that (also tried with enctype), but it's kinda weird that again it doesn't work – imans77 Nov 25 '18 at 15:27
-
1@GregorDoroschenko I used `formData.append('uploadFile', file)` and also defined a new `HttpHeaders` with `headers.append('Content-Type', 'multipart/form-data')` and the file is now sent correctly. But when I checked it, the content-type received in server is actually `multipart/octet-stream`. Is that a problem? – imans77 Nov 25 '18 at 15:40
-
after uploading successfully , how can we store those files in application folder ( example: app -> uploaded files folder) under app folder in angular. Any suggestions please. – Eswar Oct 13 '19 at 09:36
-
@Eswar, the Angular application folder is a client-side directory, you'd need to handle the storage of the file on your server-side application – Robin De Schepper Oct 19 '19 at 12:40
-
4
-
@SamarthSaxena With `$event.target.files` you can get the information from `input´-HTMLelement. In this example you read the selected files from `input` of type `file`. – Gregor Doroschenko Jan 02 '20 at 13:17
-
To allow multiple input file selections use multiple="multiple" on input tag, per https://stackoverflow.com/questions/1593225/how-to-select-multiple-files-with-input-type-file/16701951 – JavaBeast Feb 04 '20 at 17:37
-
-
what should be 'your-destination-url' if i want to store it in my project directory itself. For me it shows localhost:3000/uploads not found – Siddharth Choudhary Mar 17 '20 at 20:12
-
@SiddharthChoudhary Above explanation is related to file upload to server. For saving files to local file system you should look to FileSaver interface or use third party packages like `file-saver`. – Gregor Doroschenko Mar 20 '20 at 17:27
-
-
-
-
What really made it finally work for me was changing the headers from `"Content-Type": "application/json"` to `'enctype': 'multipart/form-data'` – user1037607 Aug 27 '20 at 21:39
-
1I also do next if you only need to upload a single file I pass function arguments on Chang like this: `$event.target.files[0]` or you could pass it like `$event.target.files` if you need to upload multiple files, you would also need to add argument to input `multiple` and then add it to the `FormData` object in loop like :`data.append('files[]', fileToUpliad, fileToUpload[i].name);` – Utmost Creator Nov 12 '20 at 17:36
-
3how do i set the headers in your example? How do i define `yourHeadersConfig`? – Sithys Jan 12 '21 at 12:46
-
@GregorDoroschenko Can you please share the corresponding backend code where you read the excel file? – Mathias Noack Sep 02 '22 at 13:16
-
@MathiasNoack Sorry, I don't have the corresponding backend code anymore. – Gregor Doroschenko Sep 02 '22 at 13:53
This way I implement upload file to web API in project.
I share for whom concern.
const formData: FormData = new FormData();
formData.append('Image', image, image.name);
formData.append('ComponentId', componentId);
return this.http.post('/api/dashboard/UploadImage', formData);
Step by step
ASP.NET Web API
[HttpPost]
[Route("api/dashboard/UploadImage")]
public HttpResponseMessage UploadImage()
{
string imageName = null;
var httpRequest = HttpContext.Current.Request;
//Upload Image
var postedFile = httpRequest.Files["Image"];
//Create custom filename
if (postedFile != null)
{
imageName = new String(Path.GetFileNameWithoutExtension(postedFile.FileName).Take(10).ToArray()).Replace(" ", "-");
imageName = imageName + DateTime.Now.ToString("yymmssfff") + Path.GetExtension(postedFile.FileName);
var filePath = HttpContext.Current.Server.MapPath("~/Images/" + imageName);
postedFile.SaveAs(filePath);
}
}
HTML form
<form #imageForm=ngForm (ngSubmit)="OnSubmit(Image)">
<img [src]="imageUrl" class="imgArea">
<div class="image-upload">
<label for="file-input">
<img src="upload.jpg" />
</label>
<input id="file-input" #Image type="file" (change)="handleFileInput($event.target.files)" />
<button type="submit" class="btn-large btn-submit" [disabled]="Image.value=='' || !imageForm.valid"><i
class="material-icons">save</i></button>
</div>
</form>
TS file to use API
OnSubmit(Image) {
this.dashboardService.uploadImage(this.componentId, this.fileToUpload).subscribe(
data => {
console.log('done');
Image.value = null;
this.imageUrl = "/assets/img/logo.png";
}
);
}
Service TS
uploadImage(componentId, image) {
const formData: FormData = new FormData();
formData.append('Image', image, image.name);
formData.append('ComponentId', componentId);
return this.http.post('/api/dashboard/UploadImage', formData);
}

- 19,744
- 8
- 48
- 83

- 24,551
- 7
- 52
- 62
Very easy and fastest method is using ng2-file-upload.
Install ng2-file-upload via npm. npm i ng2-file-upload --save
At first import module in your module.
import { FileUploadModule } from 'ng2-file-upload';
Add it to [imports] under @NgModule:
imports: [ ... FileUploadModule, ... ]
Markup:
<input ng2FileSelect type="file" accept=".xml" [uploader]="uploader"/>
In your commponent ts:
import { FileUploader } from 'ng2-file-upload';
...
uploader: FileUploader = new FileUploader({ url: "api/your_upload", removeAfterUpload: false, autoUpload: true });
It`is simplest usage of this. To know all power of this see demo

- 5,155
- 16
- 92
- 189

- 2,650
- 26
- 24
-
5how to get response when image uploaded? what will be the response, documentation is missing this part. – Muhammad Shahzad Apr 17 '19 at 21:53
-
3WARNING: ng2-file-upload doesn't use angular's http service so the calls will not be picked up by the MSAL interceptor so an access token will not be added to the Authorization header automatically. – ChiefTwoPencils Dec 10 '20 at 20:06
- HTML
<div class="form-group">
<label for="file">Choose File</label><br /> <input type="file" id="file" (change)="uploadFiles($event.target.files)">
</div>
<button type="button" (click)="RequestUpload()">Ok</button>
- ts File
public formData = new FormData();
ReqJson: any = {};
uploadFiles( file ) {
console.log( 'file', file )
for ( let i = 0; i < file.length; i++ ) {
this.formData.append( "file", file[i], file[i]['name'] );
}
}
RequestUpload() {
this.ReqJson["patientId"] = "12"
this.ReqJson["requesterName"] = "test1"
this.ReqJson["requestDate"] = "1/1/2019"
this.ReqJson["location"] = "INDIA"
this.formData.append( 'Info', JSON.stringify( this.ReqJson ) )
this.http.post( '/Request', this.formData )
.subscribe(( ) => {
});
}
- Backend Spring(java file)
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
@Controller
public class Request {
private static String UPLOADED_FOLDER = "c://temp//";
@PostMapping("/Request")
@ResponseBody
public String uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("Info") String Info) {
System.out.println("Json is" + Info);
if (file.isEmpty()) {
return "No file attached";
}
try {
// Get the file and save it somewhere
byte[] bytes = file.getBytes();
Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
Files.write(path, bytes);
} catch (IOException e) {
e.printStackTrace();
}
return "Succuss";
}
}
We have to create a folder "temp" in C drive, then this code will print the Json in console and save the uploaded file in the created folder

- 1,193
- 17
- 25
-
How do we retrieve that file? Do you have some guidance over that? – Siddharth Choudhary Mar 18 '20 at 13:14
-
Also my spring server is running on 8080 and angular's is running on 3000. Now when i mark server_url as localhost:8080/api/uploadForm it says that cors not allowed! – Siddharth Choudhary Mar 18 '20 at 13:43
-
byte[] bytes = file.getBytes(); it will give the byte stream..you can convert it to file, for cors problem you can find solution in google – Shafeeq Mohammed Mar 19 '20 at 16:33
-
Is there any posibilty to return alert that there is no selected file if the user directly clicked on "ok" button without selecting any file before ?` – Catalina Aug 13 '20 at 09:48
-
@Siddharth Add this to your spring controller annotation: @CrossOrigin(origins = "http://localhost:8080") – Hrvoje T Jun 16 '21 at 14:39
First, you need to set up HttpClient in your Angular project.
Open the src/app/app.module.ts file, import HttpClientModule and add it to the imports array of the module as follows:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Next, generate a component:
$ ng generate component home
Next, generate an upload service:
$ ng generate service upload
Next, open the src/app/upload.service.ts file as follows:
import { HttpClient, HttpEvent, HttpErrorResponse, HttpEventType } from '@angular/common/http';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class UploadService {
SERVER_URL: string = "https://file.io/";
constructor(private httpClient: HttpClient) { }
public upload(formData) {
return this.httpClient.post<any>(this.SERVER_URL, formData, {
reportProgress: true,
observe: 'events'
});
}
}
Next, open the src/app/home/home.component.ts file, and start by adding the following imports:
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { HttpEventType, HttpErrorResponse } from '@angular/common/http';
import { of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { UploadService } from '../upload.service';
Next, define the fileUpload and files variables and inject UploadService as follows:
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
@ViewChild("fileUpload", {static: false}) fileUpload: ElementRef;files = [];
constructor(private uploadService: UploadService) { }
Next, define the uploadFile() method:
uploadFile(file) {
const formData = new FormData();
formData.append('file', file.data);
file.inProgress = true;
this.uploadService.upload(formData).pipe(
map(event => {
switch (event.type) {
case HttpEventType.UploadProgress:
file.progress = Math.round(event.loaded * 100 / event.total);
break;
case HttpEventType.Response:
return event;
}
}),
catchError((error: HttpErrorResponse) => {
file.inProgress = false;
return of(`${file.data.name} upload failed.`);
})).subscribe((event: any) => {
if (typeof (event) === 'object') {
console.log(event.body);
}
});
}
Next, define the uploadFiles() method which can be used to upload multiple image files:
private uploadFiles() {
this.fileUpload.nativeElement.value = '';
this.files.forEach(file => {
this.uploadFile(file);
});
}
Next, define the onClick() method:
onClick() {
const fileUpload = this.fileUpload.nativeElement;fileUpload.onchange = () => {
for (let index = 0; index < fileUpload.files.length; index++)
{
const file = fileUpload.files[index];
this.files.push({ data: file, inProgress: false, progress: 0});
}
this.uploadFiles();
};
fileUpload.click();
}
Next, we need to create the HTML template of our image upload UI. Open the src/app/home/home.component.html file and add the following content:
<div [ngStyle]="{'text-align':center; 'margin-top': 100px;}">
<button mat-button color="primary" (click)="fileUpload.click()">choose file</button>
<button mat-button color="warn" (click)="onClick()">Upload</button>
<input [hidden]="true" type="file" #fileUpload id="fileUpload" name="fileUpload" multiple="multiple" accept="image/*" />
</div>
Ok, as this thread appears among the first results of google and for other users having the same question, you don't have to reivent the wheel as pointed by trueboroda there is the ng2-file-upload library which simplify this process of uploading a file with angular 6 and 7 all you need to do is:
Install the latest Angular CLI
yarn add global @angular/cli
Then install rx-compat for compatibility concern
npm install rxjs-compat --save
Install ng2-file-upload
npm install ng2-file-upload --save
Import FileSelectDirective Directive in your module.
import { FileSelectDirective } from 'ng2-file-upload';
Add it to [declarations] under @NgModule:
declarations: [ ... FileSelectDirective , ... ]
In your component
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
...
export class AppComponent implements OnInit {
public uploader: FileUploader = new FileUploader({url: URL, itemAlias: 'photo'});
}
Template
<input type="file" name="photo" ng2FileSelect [uploader]="uploader" />
For better understanding you can check this link: How To Upload a File With Angular 6/7

- 393
- 6
- 10
-
1Thanks for the link. Uploading works fine on desktop but I cannot for the life of me get uploads to work on mobile devices like iOS. I can select a file from camera roll but when I upload it always fails. Any ideas? FYI, running this in mobile safari, not in an app that is installed. – ScottN Jun 20 '19 at 16:59
-
1Hi @ScottN and your are welcome, maybe the problem comes from the browser your are using? did you test it with another one ? – Mohamed Makkaoui Jun 25 '19 at 11:25
-
1Hi @Mohamed Makkaoui thanks for the reply. I did try it in Chrome on iOS and still the same result. I'm curious if this is a header issue when posting to the server? I'm using a custom WebAPI written in .Net and NOT AWS FYI. – ScottN Jul 10 '19 at 00:15
-
1Hi @ScottN we won't be able to know if it's a header issue until you debug your code using this link https://developers.google.com/web/tools/chrome-devtools/remote-debugging/ and see what error message do you get. – Mohamed Makkaoui Jul 12 '19 at 10:53
-
On the other side of things, you don't need a package to implement a simple file upload. The API's are all there, you dont have to reinvent anything. – Kim Nov 03 '20 at 10:36
I am using Angular 5.2.11, I like the solution provided by Gregor Doroschenko, however I noticed that the uploaded file is of zero bytes, I had to make a small change to get it to work for me.
postFile(fileToUpload: File): Observable<boolean> {
const endpoint = 'your-destination-url';
return this.httpClient
.post(endpoint, fileToUpload, { headers: yourHeadersConfig })
.map(() => { return true; })
.catch((e) => this.handleError(e));
}
The following lines (formData) didn't work for me.
const formData: FormData = new FormData();
formData.append('fileKey', fileToUpload, fileToUpload.name);
https://github.com/amitrke/ngrke/blob/master/src/app/services/fileupload.service.ts

- 81
- 1
- 2
Personally I'm doing this using ngx-material-file-input for the front-end, and Firebase for the back-end. More precisely Cloud Storage for Firebase for the back-end combined with Cloud Firestore. Below an example, which limits file to be not larger than 20 MB, and accepts only certain file extensions. I'm also using Cloud Firestore for storing links to the uploaded files, but you can skip this.
contact.component.html
<mat-form-field>
<!--
Accept only files in the following format: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx. However, this is easy to bypass, Cloud Storage rules has been set up on the back-end side.
-->
<ngx-mat-file-input
[accept]="[
'.doc',
'.docx',
'.jpg',
'.jpeg',
'.pdf',
'.png',
'.xls',
'.xlsx'
]"
(change)="uploadFile($event)"
formControlName="fileUploader"
multiple
aria-label="Here you can add additional files about your project, which can be helpeful for us."
placeholder="Additional files"
title="Additional files"
type="file"
>
</ngx-mat-file-input>
<mat-icon matSuffix>folder</mat-icon>
<mat-hint
>Accepted formats: DOC, DOCX, JPG, JPEG, PDF, PNG, XLS and XLSX,
maximum files upload size: 20 MB.
</mat-hint>
<!--
Non-null assertion operators are required to let know the compiler that this value is not empty and exists.
-->
<mat-error
*ngIf="contactForm.get('fileUploader')!.hasError('maxContentSize')"
>
This size is too large,
<strong
>maximum acceptable upload size is
{{
contactForm.get('fileUploader')?.getError('maxContentSize')
.maxSize | byteFormat
}}</strong
>
(uploaded size:
{{
contactForm.get('fileUploader')?.getError('maxContentSize')
.actualSize | byteFormat
}}).
</mat-error>
</mat-form-field>
contact.component.ts (size validator part)
import { FileValidator } from 'ngx-material-file-input';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
/**
* @constructor
* @description Creates a new instance of this component.
* @param {formBuilder} - an abstraction class object to create a form group control for the contact form.
*/
constructor(
private angularFirestore: AngularFirestore,
private angularFireStorage: AngularFireStorage,
private formBuilder: FormBuilder
) {}
public maxFileSize = 20971520;
public contactForm: FormGroup = this.formBuilder.group({
fileUploader: [
'',
Validators.compose([
FileValidator.maxContentSize(this.maxFileSize),
Validators.maxLength(512),
Validators.minLength(2)
])
]
})
contact.component.ts (file uploader part)
import { AngularFirestore } from '@angular/fire/firestore';
import {
AngularFireStorage,
AngularFireStorageReference,
AngularFireUploadTask
} from '@angular/fire/storage';
import { catchError, finalize } from 'rxjs/operators';
import { throwError } from 'rxjs';
public downloadURL: string[] = [];
/**
* @description Upload additional files to Cloud Firestore and get URL to the files.
* @param {event} - object of sent files.
* @returns {void}
*/
public uploadFile(event: any): void {
// Iterate through all uploaded files.
for (let i = 0; i < event.target.files.length; i++) {
const randomId = Math.random()
.toString(36)
.substring(2); // Create random ID, so the same file names can be uploaded to Cloud Firestore.
const file = event.target.files[i]; // Get each uploaded file.
// Get file reference.
const fileRef: AngularFireStorageReference = this.angularFireStorage.ref(
randomId
);
// Create upload task.
const task: AngularFireUploadTask = this.angularFireStorage.upload(
randomId,
file
);
// Upload file to Cloud Firestore.
task
.snapshotChanges()
.pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe((downloadURL: string) => {
this.angularFirestore
.collection(process.env.FIRESTORE_COLLECTION_FILES!) // Non-null assertion operator is required to let know the compiler that this value is not empty and exists.
.add({ downloadURL: downloadURL });
this.downloadURL.push(downloadURL);
});
}),
catchError((error: any) => {
return throwError(error);
})
)
.subscribe();
}
}
storage.rules
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read; // Required in order to send this as attachment.
// Allow write files Firebase Storage, only if:
// 1) File is no more than 20MB
// 2) Content type is in one of the following formats: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx.
allow write: if request.resource.size <= 20 * 1024 * 1024
&& (request.resource.contentType.matches('application/msword')
|| request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
|| request.resource.contentType.matches('image/jpg')
|| request.resource.contentType.matches('image/jpeg')
|| request.resource.contentType.matches('application/pdf')
|| request.resource.contentType.matches('image/png')
|| request.resource.contentType.matches('application/vnd.ms-excel')
|| request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
}
}
}

- 8,508
- 6
- 68
- 94
-
2Look great, but why do you need `toString()` at the contactForm declaration? – trungk18 Aug 27 '19 at 03:49
-
1@trungk18 check it once again, and you're right the `toString()` is useless, edited my answer. For those who would read this comment, at the end of `fileUploader` in **contact.component.ts** I had `])].toString()})`. Now it's simply: `])]})`. – Daniel Danielecki Aug 27 '19 at 15:20
Complete example of File upload using Angular and nodejs(express)
HTML Code
<div class="form-group">
<label for="file">Choose File</label><br/>
<input type="file" id="file" (change)="uploadFile($event.target.files)" multiple>
</div>
TS Component Code
uploadFile(files) {
console.log('files', files)
var formData = new FormData();
for(let i =0; i < files.length; i++){
formData.append("files", files[i], files[i]['name']);
}
this.httpService.httpPost('/fileUpload', formData)
.subscribe((response) => {
console.log('response', response)
},
(error) => {
console.log('error in fileupload', error)
})
}
Node Js code
fileUpload API controller
function start(req, res) {
fileUploadService.fileUpload(req, res)
.then(fileUploadServiceResponse => {
res.status(200).send(fileUploadServiceResponse)
})
.catch(error => {
res.status(400).send(error)
})
}
module.exports.start = start
Upload service using multer
const multer = require('multer') // import library
const moment = require('moment')
const q = require('q')
const _ = require('underscore')
const fs = require('fs')
const dir = './public'
/** Store file on local folder */
let storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public')
},
filename: function (req, file, cb) {
let date = moment(moment.now()).format('YYYYMMDDHHMMSS')
cb(null, date + '_' + file.originalname.replace(/-/g, '_').replace(/ /g, '_'))
}
})
/** Upload files */
let upload = multer({ storage: storage }).array('files')
/** Exports fileUpload function */
module.exports = {
fileUpload: function (req, res) {
let deferred = q.defer()
/** Create dir if not exist */
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
console.log(`\n\n ${dir} dose not exist, hence created \n\n`)
}
upload(req, res, function (err) {
if (req && (_.isEmpty(req.files))) {
deferred.resolve({ status: 200, message: 'File not attached', data: [] })
} else {
if (err) {
deferred.reject({ status: 400, message: 'error', data: err })
} else {
deferred.resolve({
status: 200,
message: 'File attached',
filename: _.pluck(req.files,
'filename'),
data: req.files
})
}
}
})
return deferred.promise
}
}

- 3,365
- 26
- 26
-
1
-
@James httpService is http module of angular to make http call to server. You can use any http service you want.import { HttpClientModule } from '@angular/common/http'; – Rohit Parte Jan 04 '20 at 12:09
In Angular 7/8/9
Source Link
Using Bootstrap Form
<form>
<div class="form-group">
<fieldset class="form-group">
<label>Upload Logo</label>
{{imageError}}
<div class="custom-file fileInputProfileWrap">
<input type="file" (change)="fileChangeEvent($event)" class="fileInputProfile">
<div class="img-space">
<ng-container *ngIf="isImageSaved; else elseTemplate">
<img [src]="cardImageBase64" />
</ng-container>
<ng-template #elseTemplate>
<img src="./../../assets/placeholder.png" class="img-responsive">
</ng-template>
</div>
</div>
</fieldset>
</div>
<a class="btn btn-danger" (click)="removeImage()" *ngIf="isImageSaved">Remove</a>
</form>
In Component Class
fileChangeEvent(fileInput: any) {
this.imageError = null;
if (fileInput.target.files && fileInput.target.files[0]) {
// Size Filter Bytes
const max_size = 20971520;
const allowed_types = ['image/png', 'image/jpeg'];
const max_height = 15200;
const max_width = 25600;
if (fileInput.target.files[0].size > max_size) {
this.imageError =
'Maximum size allowed is ' + max_size / 1000 + 'Mb';
return false;
}
if (!_.includes(allowed_types, fileInput.target.files[0].type)) {
this.imageError = 'Only Images are allowed ( JPG | PNG )';
return false;
}
const reader = new FileReader();
reader.onload = (e: any) => {
const image = new Image();
image.src = e.target.result;
image.onload = rs => {
const img_height = rs.currentTarget['height'];
const img_width = rs.currentTarget['width'];
console.log(img_height, img_width);
if (img_height > max_height && img_width > max_width) {
this.imageError =
'Maximum dimentions allowed ' +
max_height +
'*' +
max_width +
'px';
return false;
} else {
const imgBase64Path = e.target.result;
this.cardImageBase64 = imgBase64Path;
this.isImageSaved = true;
// this.previewImagePath = imgBase64Path;
}
};
};
reader.readAsDataURL(fileInput.target.files[0]);
}
}
removeImage() {
this.cardImageBase64 = null;
this.isImageSaved = false;
}

- 9,626
- 4
- 66
- 46
-
Could you tell me whether pls Is the file is getting saved in the local folder? – Venkata Shivaram Oct 28 '21 at 08:40
-
Here is how I did it to upload the excel files:
Directory structure:
app
|-----uploadcomponent
|-----uploadcomponent.module.ts
|-----uploadcomponent.html
|-----app.module.ts
|-----app.component.ts
|-----app.service.ts
uploadcomponent.html
<div>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input type="file" name="profile" enctype="multipart/form-data" accept=".xlsm,application/msexcel" (change)="onChange($event)" />
<button type="submit">Upload Template</button>
<button id="delete_button" class="delete_button" type="reset"><i class="fa fa-trash"></i></button>
</form>
</div>
uploadcomponent.ts
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
....
export class UploadComponent implements OnInit {
form: FormGroup;
constructor(private formBuilder: FormBuilder, private uploadService: AppService) {}
ngOnInit() {
this.form = this.formBuilder.group({
profile: ['']
});
}
onChange(event) {
if (event.target.files.length > 0) {
const file = event.target.files[0];
this.form.get('profile').setValue(file);
console.log(this.form.get('profile').value)
}
}
onSubmit() {
const formData = new FormData();
formData.append('file', this.form.get('profile').value);
this.uploadService.upload(formData).subscribe(
(res) => {
this.response = res;
console.log(res);
},
(err) => {
console.log(err);
});
}
}
app.service.ts
upload(formData) {
const endpoint = this.service_url+'upload/';
const httpOptions = headers: new HttpHeaders({ <<<< Changes are here
'Authorization': 'token xxxxxxx'})
};
return this.http.post(endpoint, formData, httpOptions);
}
In Backend I use DJango REST Framework.
models.py
from __future__ import unicode_literals
from django.db import models
from django.db import connection
from django_mysql.models import JSONField, Model
import uuid
import os
def change_filename(instance, filename):
extension = filename.split('.')[-1]
file_name = os.path.splitext(filename)[0]
uuid_name = uuid.uuid4()
return file_name+"_"+str(uuid_name)+"."+extension
class UploadTemplate (Model):
id = models.AutoField(primary_key=True)
file = models.FileField(blank=False, null=False, upload_to=change_filename)
def __str__(self):
return str(self.file.name)
views.py.
class UploadView(APIView):
serializer_class = UploadSerializer
parser_classes = [MultiPartParser]
def get_queryset(self):
queryset = UploadTemplate.objects.all()
return queryset
def post(self, request, *args, **kwargs):
file_serializer = UploadSerializer(data=request.data)
status = None
message = None
if file_serializer.is_valid():
file_serializer.save()
status = "Success"
message = "Success"
else:
status = "Failure"
message = "Failure!"
content = {'status': status, 'message': message}
return Response(content)
serializers.py.
from uploadtemplate.models import UploadTemplate
from rest_framework import serializers
class UploadSerializer(serializers.ModelSerializer):
class Meta:
model = UploadTemplate
fields = '__all__'
urls.py.
router.register(r'uploadtemplate', uploadtemplateviews.UploadTemplateView,
base_name='UploadTemplate')
urlpatterns = [
....
url(r'upload/', uploadtemplateviews.UploadTemplateView.as_view()),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
MEDIA_URL and MEDIA_ROOT is defined in settings.py of the project.
Thanks!

- 1,800
- 1
- 13
- 16
Try this
Install
npm install primeng --save
Import
import {FileUploadModule} from 'primeng/primeng';
Html
<p-fileUpload name="myfile[]" url="./upload.php" multiple="multiple"
accept="image/*" auto="auto"></p-fileUpload>

- 1,140
- 1
- 9
- 17
-
1i tired using the above example. But i am getting ./upload.php not found. – Sandeep Kamath Apr 10 '18 at 10:09
-
4You should provide your URL where it should be loaded instead of upload.php @sandeep kamath – Vignesh Apr 20 '18 at 02:19
-
1@Vignesh thanks for your reply. But i found that i don't give the url attribute at all it load the file, should be the default one. – Sandeep Kamath Apr 20 '18 at 10:28
-
1Can u please explain how we can receive the file in php if we are doing in this method. – Shaikh Arbaaz May 08 '18 at 10:59
create-profile.html
<body>
<h1 class="font-weight-bold" >Create Advertistment</h1>
<hr />
<form [formGroup]="form" (submit)="onSubmit()">
<div>
<label class="font-weight-bold">Insert Subject name</label>
<br>
<input formControlName="name" type="text" placeholder="Enter name..." />
</div>
<div>
<br>
<label class="font-weight-bold">Select the Advertistment</label>
<br>
<input (change)="onFileSelect($event)" type="file" />
</div>
<br>
<!--<div *ngIf="imageData">
<img [src]="imageData" [alt]="form.value.name" />
</div>-->
<div>
<label class="font-weight-bold">Upload the Advertistment</label>
<br>
<button type="submit" class="btn btn-success" >Upload Advertistment</button>
</div>
</form>
</body>
create-profile.ts
import { Component, OnInit } from "@angular/core";
import { FormGroup, FormControl } from "@angular/forms";
import { Profile } from "../../models/Profile";
import { ProfileService } from "src/app/services/profile.service";
@Component({
selector: "app-create-profile",
templateUrl: "./create-profile.component.html",
styleUrls: ["./create-profile.component.css"],
})
export class CreateProfileComponent implements OnInit {
form: FormGroup;
profile: Profile;
imageData: string;
constructor(private profileService: ProfileService) {}
ngOnInit(): void {
this.form = new FormGroup({
name: new FormControl(null),
image: new FormControl(null),
});
}
onFileSelect(event: Event) {
const file = (event.target as HTMLInputElement).files[0];
this.form.patchValue({ image: file });
const allowedMimeTypes = ["image/png", "image/jpeg", "image/jpg"];
if (file && allowedMimeTypes.includes(file.type)) {
const reader = new FileReader();
reader.onload = () => {
this.imageData = reader.result as string;
};
reader.readAsDataURL(file);
}
}
onSubmit() {
this.profileService.addProfile(this.form.value.name, this.form.value.image);
this.form.reset();
this.imageData = null;
}
}
profile.service.ts
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { map } from "rxjs/operators";
import { Profile } from "../models/Profile";
import { Subject } from "rxjs";
@Injectable({
providedIn: "root",
})
export class ProfileService {
private profiles: Profile[] = [];
private profiles$ = new Subject<Profile[]>();
readonly url = "http://localhost:3000/api/profiles";
constructor(private http: HttpClient) {}
getProfiles() {
this.http
.get<{ profiles: Profile[] }>(this.url)
.pipe(
map((profileData) => {
return profileData.profiles;
})
)
.subscribe((profiles) => {
this.profiles = profiles;
this.profiles$.next(this.profiles);
});
}
getProfilesStream() {
return this.profiles$.asObservable();
}
addProfile(name: string, image: File): void {
const profileData = new FormData();
profileData.append("name", name);
profileData.append("image", image, name);
this.http
.post<{ profile: Profile }>(this.url, profileData)
.subscribe((profileData) => {
const profile: Profile = {
_id: profileData.profile._id,
name: name,
imagePath: profileData.profile.imagePath,
};
this.profiles.push(profile);
this.profiles$.next(this.profiles);
});
}
}
Profile.ts
export interface Profile {
_id: string;
name: string;
imagePath: string;
}

- 22
- 6
In my case, I'm using http interceptor, thing is that by default my http interceptor sets content-type
header as application/json
, but for file uploading I'm using multer library.
So little bit changing my http.interceptor defines if request body is FormData it removes headers and doesn't touch access token.
Here is part of code, which made my day.
if (request.body instanceof FormData) {
request = request.clone({ headers: request.headers.delete('Content-Type', 'application/json') });
}
if (request.body instanceof FormData) {
request = request.clone({ headers: request.headers.delete('Accept', 'application/json')});
}

- 30,962
- 25
- 85
- 135

- 4,049
- 4
- 25
- 42
Progress-up has angular plugin
I am the author of this plugin.
You can have file uploads and other goodies.
The uploader has support for these:
- Lightweight and modular
- Plugin-based architecture
- No dependencies
- Track uploads with progress indicator
- Drag and drop
- Files are previewed before upload
- Dark mode support
- Available for all popular web frameworks
These are the websites you will need to learn more and download it to give it a spin.
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 06 '23 at 05:09