In this article, We will upload, list and download files using Nodejs[Express] and Angular5. The File could be pdf, doc, image or any other type, The file will be stored in Uploads folder and the filename will be stored with the user id in a MongoDB database, We can add more details like userID, FileSize, and FileType but, We will store just filename which will be retrieved from database in order to load files from Uploads folder to list files in Angular5 Frontend with Download and Delete options.
- Node Js Express Download File For Mac
- Node Js Express Download File Converter
- Nodejs Download File Stream
- Node Js Download File From Url
Starting with the Angular part.
Angular Part
Download a file from NodeJS Server using Express. Well, that is a different case than the question specified. Search for nodejs proxy file download response for best practice – Jossef Harush Sep 20 '17 at 17:13. Browse other questions tagged javascript node.js file express download or ask your own question. 7 years, 6 months.
First, Starting by creating a new project named client using Angular-Cli, In command prompt write ng new client
After that, We will create a new Component, We will call it files.
in cmd:
cd client then, ng g component files. then create a files.service.ts file inside files component. and app-routing.compoent in app component. It will look like that.
Start by adding bootstrap to index.html
index.html
<link rel='stylesheet'href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css'> |
app.module.ts
2 4 6 8 10 12 14 16 18 20 22 24 | import{BrowserModule}from'@angular/platform-browser'; import{AppRoutingModule}from'./app-routing.module'; import{FilesComponent}from'./files/files.component'; import{HttpClientModule}from'@angular/common/http'; import{FormsModule,ReactiveFormsModule}from'@angular/forms'; declarations:[ FilesComponent, imports:[ AppRoutingModule, FormsModule, ], bootstrap:[AppComponent] exportclassAppModule{} |
We have included HttpClientModule which will be used in GET and POST requests and Form modules which will be used for upload form.
app-routing.module.ts
2 4 6 8 10 12 14 16 | import{Routes,RouterModule}from'@angular/router'; import{FilesComponent}from'./files/files.component'; {path:'**',pathMatch:'full',redirectTo:'/'} imports:[RouterModule.forRoot(routes)], }) |
![Node Js Express Download File Node Js Express Download File](/uploads/1/2/6/1/126153733/448902579.png)
We will make FileComponent the component used for the main directory and also redirect any other directory to the main directory.
app.component.html
files.component.html
We will add the form HTML and list the existing files under it.
Starting with the File Upload form, We will use FileSubmit() function to handle Form submit, and onChange() function to pass File after being selected. also showing upload percentage while uploading the file.
2 4 | <form style='display:inline-block;margin:0 auto;'id='uploadForm'(ngSubmit)='FileSubmit()'enctype='multipart/form-data'> <input type='file'name='userFile'(change)='onChange($event)'/> {{uploadPercent}}% |
below the form, We will add an alert box to be shown after upload completed for 1 second.
2 | <h2 class='alert alert-success'style='margin-top:50px;'[ngStyle]='{'display':showfileuploaded}'> </h2> |
The last part which will list all uploaded files.
2 4 6 8 10 12 | <div class='row'> <div *ngFor='let file of files'class='col-md-3 text-center'style='padding:30px'> <div class='filecontainer'style='margin-bottom:100px;'> <img src='/assets/folderImg.jpg'alt='style='width:70px;height:70px;'> <h6 style='margin-top:20px;margin-bottom:40px;'>{{file.filename}}</h6> <button class='btn btn-primary block'target='_self'(click)='downloadTheFile(file.filename)'><span>Download</span></button> <button class='btn btn-danger block'(click)='deleteTheFile(file.filename)'><span>Delete</span></button> </div> </div> |
Full Code
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 | <div class='py-5 row'> <div class='container text-center'style='padding:40px 30px;background-color:#EEE;'> <form style='display:inline-block;margin:0 auto;'id='uploadForm'(ngSubmit)='FileSubmit()'enctype='multipart/form-data'> <input type='file'name='userFile'(change)='onChange($event)'/> {{uploadPercent}}% <h2 class='alert alert-success'style='margin-top:50px;'[ngStyle]='{'display':showfileuploaded}'> </h2> </div> <div class='row'> <div *ngFor='let file of files'class='col-md-3 text-center'style='padding:30px'> <div class='filecontainer'style='margin-bottom:100px;'> <img src='/assets/folderImg.jpg'alt='style='width:70px;height:70px;'> <h6 style='margin-top:20px;margin-bottom:40px;'>{{file.filename}}</h6> <button class='btn btn-primary block'target='_self'(click)='downloadTheFile(file.filename)'><span>Download</span></button> <!--<button *ngIf='ifPDF(file.filename)'class='btn btn-success block'(click)='viewTheFile(file.filename)'><span>View</span></button>--> <button class='btn btn-danger block'(click)='deleteTheFile(file.filename)'><span>Delete</span></button> </div> </div> <ng-container *ngIf='files.length 0'> <div class='container text-center'style='margin-top:20px;'> </div> </div> |
files.service.ts
2 4 6 8 10 12 14 16 18 20 22 24 26 28 | import{HttpRequest,HttpClient}from'@angular/common/http'; @Injectable() returnthis.http.get<Array<object>>(this.FileUrl); let req=newHttpRequest('POST',this.FileUrl,file,{ }); } returnthis.http.delete(this.FileUrl+filename); } |
We will use HttpRequest class in addFile() function because it allows returning Progress while uploading.
files.component.ts
Starting with the imports.
2 | import{FileService}from'./files.service'; import{HttpEventType,HttpResponse}from'@angular/common/http' |
then add the variables and injecting the FileService in the Constructor.
2 4 6 | showfileuploaded='none'; fileToUpload:File; constructor(private_fileServ:FileService){} |
uploadPercent => for File upload percentage.
showfileuploaded => for displaying “File Uploaded” alert after uploaded completed.
files => store Files after retrieving from the server.
fileToUpload => store the File that has been uploaded.
Starting with onChange() function. We will pass the file that has been selected to fileToUpload variable.
2 | this.fileToUpload=x.target.files; |
then FileSubmit() function.
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 | constformData:any=newFormData(); formData.append('uploads',file[0]['name']); this._fileServ.addFile(formData).subscribe( (event)=>{ constpercentDone=Math.round(100*event.loaded/event.total); this.uploadPercent=percentDone; }elseif(event instanceofHttpResponse){ console.log('file is completely uploaded!'); setTimeout(()=>{this.showfileuploaded='none';this.uploadPercent=0;},1000) } (err)=>{ }, console.log('done'); } } |
The function starts by creating a FormData object, then appends the file name and file content to that object.
after that passes that object to addFile() function, after that it checks the event if its type equal to HttpEventType.UploadProgress, that means the upload is still in progress. otherwise, the upload is complete.
so we can show “file uploaded” alert in the frontend. after complete, we can retrieve all files uploaded.
downloadTheFile() function.
after clicking download function, a get request is sent to the server in a new window.
2 4 | window.open('/files/'+filename); } |
deleteTheFile() function.
2 4 6 8 10 12 14 | this._fileServ.deleteFile(filename).subscribe( console.log(file); for(leti=0;i<this.files.length;i++){ this.files.splice(i,1); } } ) |
last part is calling getFiles() function inside ngOnInit()
2 | this.getFiles(); |
Full code
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100 102 | import{FileService}from'./files.service'; import{HttpEventType,HttpResponse}from'@angular/common/http'; @Component({ templateUrl:'./files.component.html', providers:[FileService] exportclassFilesComponentimplementsOnInit{ uploadPercent:number=0; files:Array<object>=[]; constructor(privaterouter:Router,privatefb:FormBuilder,private_fileServ:FileService){} ngOnInit(){ } this.fileToUpload=x.target.files; this._fileServ.getFiles().subscribe( this.files=data['files']; }, console.log('file upload error '+JSON.stringify(err)); ) constformData:any=newFormData(); formData.append('uploads',file[0]['name']); console.log(formData); if(event.typeHttpEventType.UploadProgress){ constpercentDone=Math.round(100*event.loaded/event.total); this.uploadPercent=percentDone; console.log('file is completely uploaded!'); setTimeout(()=>{this.showfileuploaded='none';this.uploadPercent=0;},1000) console.log(event); (err)=>{ ()=>{ this.getFiles(); ) downloadTheFile=function(filename){ this._fileServ.deleteFile(filename).subscribe( console.log(file); for(leti=0;i<this.files.length;i++){ this.files.splice(i,1); } } ) } |
The Frontend part is completed, We will start the Backend, part.
create The main file server.js, files.js, and uploads folder.
server.js function.
2 4 6 8 10 12 14 16 18 20 22 24 26 28 | varpath=require('path'); varejs=require('ejs'); varapp=express(); app.set('views',path.resolve(__dirname,'../client/dist')); app.engine('html',require('ejs').renderFile); app.use(express.static(path.resolve(__dirname,'../client/dist'))); app.use(bodyParser.urlencoded({extended:true})); app.use(fileUpload()); varfiles=require('./files'); app.get('/*',(req,res)=>{ res.sendFile(path.resolve(__dirname,'../client/dist/index.html')); app.listen(port,function(){ }); |
files.js file.
require the important libs
2 4 | varmongojs=require('mongojs'); varpath=require('path'); |
initiate express router, current directory and connect to MongoDB database, We will use mlab.
2 4 | vardb=mongojs('mongodb://-----.mlab.com:41474/meanapp1',['files']); varDIR=path.resolve(__dirname,'uploads/'); |
Don’t forget to add your MongoDB database link.
the rest is routing functions to get all files, download and delete a file.
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 | console.log(req.files); let file=req.files.uploads, file.mv(path.resolve(DIR,filename),(err)=>{ console.log(err); else }); if(err)returnres.status(403).json({'result':'error','message':'something is wrong'}); console.log('file added to database'); }) }); router.get('/',(req,res)=>{ if(err) returnres.status(403).json({'result':'error','message':'something is wrong'}); returnres.send({'message':'success','files':files}); }); router.get('/:filename',(req,res)=>{ db.files.find({},(err,files)=>{ returnres.status(403).json({'result':'error','message':'something is wrong'}); varfilePath=path.resolve(DIR,req.params.filename); varmimetype=mime.lookup(path.resolve(DIR,req.params.filename)); }); router.delete('/:filename',(req,res)=>{ db.files.remove({$and:[{filename:req.params.filename}]},(err,file)=>{ returnres.status(404).json({'result':'error','message':'something is wrong'}); fs.unlink(path.resolve(DIR,req.params.filename),(err)=>{ }); }); |
files.js full code
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 | varmongojs=require('mongojs'); varpath=require('path'); varrouter=express.Router(); vardb=mongojs('mongodb://--------.mlab.com:41474/meanapp1',['files']); varDIR=path.resolve(__dirname,'uploads/'); router.post('/',(req,res)=>{ if(req.files){ filename=file.name; if(err){ } console.log('Done'); db.files.save({'filename':filename},(err,file)=>{ if(err)returnres.status(403).json({'result':'error','message':'something is wrong'}); console.log('file added to database'); }) }); router.get('/',(req,res)=>{ if(err) returnres.status(403).json({'result':'error','message':'something is wrong'}); returnres.send({'message':'success','files':files}); }); router.get('/:filename',(req,res)=>{ db.files.find({},(err,files)=>{ returnres.status(403).json({'result':'error','message':'something is wrong'}); varfilePath=path.resolve(DIR,req.params.filename); res.download(filePath,req.params.filename); }); db.files.remove({$and:[{filename:req.params.filename}]},(err,file)=>{ returnres.status(404).json({'result':'error','message':'something is wrong'}); fs.unlink(path.resolve(DIR,req.params.filename),(err)=>{ }); }); |
The result:
To add a view option for PDF files check this post How to view PDF files in Angular 5
Related
In this article, We will upload, list and download files using Nodejs[Express] and Angular5. The File could be pdf, doc, image or any other type, The file will be stored in Uploads folder and the filename will be stored with the user id in a MongoDB database, We can add more details like userID, FileSize, and FileType but, We will store just filename which will be retrieved from database in order to load files from Uploads folder to list files in Angular5 Frontend with Download and Delete options.
Starting with the Angular part.
Angular Part
First, Starting by creating a new project named client using Angular-Cli, In command prompt write ng new client
After that, We will create a new Component, We will call it files.
in cmd:
cd client then, ng g component files. then create a files.service.ts file inside files component. and app-routing.compoent in app component. It will look like that.
Start by adding bootstrap to index.html
index.html
<link rel='stylesheet'href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css'> |
app.module.ts
2 4 6 8 10 12 14 16 18 20 22 24 | import{BrowserModule}from'@angular/platform-browser'; import{AppRoutingModule}from'./app-routing.module'; import{FilesComponent}from'./files/files.component'; import{HttpClientModule}from'@angular/common/http'; import{FormsModule,ReactiveFormsModule}from'@angular/forms'; declarations:[ FilesComponent, imports:[ AppRoutingModule, FormsModule, ], bootstrap:[AppComponent] exportclassAppModule{} |
We have included HttpClientModule which will be used in GET and POST requests and Form modules which will be used for upload form.
app-routing.module.ts
2 4 6 8 10 12 14 16 | import{Routes,RouterModule}from'@angular/router'; import{FilesComponent}from'./files/files.component'; {path:'**',pathMatch:'full',redirectTo:'/'} imports:[RouterModule.forRoot(routes)], }) |
We will make FileComponent the component used for the main directory and also redirect any other directory to the main directory.
app.component.html
files.component.html
We will add the form HTML and list the existing files under it.
Starting with the File Upload form, We will use FileSubmit() function to handle Form submit, and onChange() function to pass File after being selected. also showing upload percentage while uploading the file.
2 4 | <form style='display:inline-block;margin:0 auto;'id='uploadForm'(ngSubmit)='FileSubmit()'enctype='multipart/form-data'> <input type='file'name='userFile'(change)='onChange($event)'/> {{uploadPercent}}% |
Node Js Express Download File For Mac
below the form, We will add an alert box to be shown after upload completed for 1 second.
2 | <h2 class='alert alert-success'style='margin-top:50px;'[ngStyle]='{'display':showfileuploaded}'> </h2> |
The last part which will list all uploaded files.
2 4 6 8 10 12 | <div class='row'> <div *ngFor='let file of files'class='col-md-3 text-center'style='padding:30px'> <div class='filecontainer'style='margin-bottom:100px;'> <img src='/assets/folderImg.jpg'alt='style='width:70px;height:70px;'> <h6 style='margin-top:20px;margin-bottom:40px;'>{{file.filename}}</h6> <button class='btn btn-primary block'target='_self'(click)='downloadTheFile(file.filename)'><span>Download</span></button> <button class='btn btn-danger block'(click)='deleteTheFile(file.filename)'><span>Delete</span></button> </div> </div> |
Full Code
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 | <div class='py-5 row'> <div class='container text-center'style='padding:40px 30px;background-color:#EEE;'> <form style='display:inline-block;margin:0 auto;'id='uploadForm'(ngSubmit)='FileSubmit()'enctype='multipart/form-data'> <input type='file'name='userFile'(change)='onChange($event)'/> {{uploadPercent}}% <h2 class='alert alert-success'style='margin-top:50px;'[ngStyle]='{'display':showfileuploaded}'> </h2> </div> <div class='row'> <div *ngFor='let file of files'class='col-md-3 text-center'style='padding:30px'> <div class='filecontainer'style='margin-bottom:100px;'> <img src='/assets/folderImg.jpg'alt='style='width:70px;height:70px;'> <h6 style='margin-top:20px;margin-bottom:40px;'>{{file.filename}}</h6> <button class='btn btn-primary block'target='_self'(click)='downloadTheFile(file.filename)'><span>Download</span></button> <!--<button *ngIf='ifPDF(file.filename)'class='btn btn-success block'(click)='viewTheFile(file.filename)'><span>View</span></button>--> <button class='btn btn-danger block'(click)='deleteTheFile(file.filename)'><span>Delete</span></button> </div> </div> <ng-container *ngIf='files.length 0'> <div class='container text-center'style='margin-top:20px;'> </div> </div> |
files.service.ts
2 4 6 8 10 12 14 16 18 20 22 24 26 28 | import{HttpRequest,HttpClient}from'@angular/common/http'; @Injectable() returnthis.http.get<Array<object>>(this.FileUrl); let req=newHttpRequest('POST',this.FileUrl,file,{ }); } returnthis.http.delete(this.FileUrl+filename); } |
We will use HttpRequest class in addFile() function because it allows returning Progress while uploading.
files.component.ts
Starting with the imports.
2 | import{FileService}from'./files.service'; import{HttpEventType,HttpResponse}from'@angular/common/http' |
then add the variables and injecting the FileService in the Constructor.
2 4 6 | showfileuploaded='none'; fileToUpload:File; constructor(private_fileServ:FileService){} |
uploadPercent => for File upload percentage.
showfileuploaded => for displaying “File Uploaded” alert after uploaded completed.
files => store Files after retrieving from the server.
fileToUpload => store the File that has been uploaded.
Starting with onChange() function. We will pass the file that has been selected to fileToUpload variable.
2 | this.fileToUpload=x.target.files; |
then FileSubmit() function.
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 | constformData:any=newFormData(); formData.append('uploads',file[0]['name']); this._fileServ.addFile(formData).subscribe( (event)=>{ constpercentDone=Math.round(100*event.loaded/event.total); this.uploadPercent=percentDone; }elseif(event instanceofHttpResponse){ console.log('file is completely uploaded!'); setTimeout(()=>{this.showfileuploaded='none';this.uploadPercent=0;},1000) } (err)=>{ }, console.log('done'); } } |
The function starts by creating a FormData object, then appends the file name and file content to that object.
after that passes that object to addFile() function, after that it checks the event if its type equal to HttpEventType.UploadProgress, that means the upload is still in progress. otherwise, the upload is complete.
so we can show “file uploaded” alert in the frontend. after complete, we can retrieve all files uploaded.
downloadTheFile() function.
after clicking download function, a get request is sent to the server in a new window.
2 4 | window.open('/files/'+filename); } |
deleteTheFile() function.
Node Js Express Download File Converter
2 4 6 8 10 12 14 | this._fileServ.deleteFile(filename).subscribe( console.log(file); for(leti=0;i<this.files.length;i++){ this.files.splice(i,1); } } ) |
last part is calling getFiles() function inside ngOnInit()
2 | this.getFiles(); |
Full code
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100 102 | import{FileService}from'./files.service'; import{HttpEventType,HttpResponse}from'@angular/common/http'; @Component({ templateUrl:'./files.component.html', providers:[FileService] exportclassFilesComponentimplementsOnInit{ uploadPercent:number=0; files:Array<object>=[]; constructor(privaterouter:Router,privatefb:FormBuilder,private_fileServ:FileService){} ngOnInit(){ } this.fileToUpload=x.target.files; this._fileServ.getFiles().subscribe( this.files=data['files']; }, console.log('file upload error '+JSON.stringify(err)); ) constformData:any=newFormData(); formData.append('uploads',file[0]['name']); console.log(formData); if(event.typeHttpEventType.UploadProgress){ constpercentDone=Math.round(100*event.loaded/event.total); this.uploadPercent=percentDone; console.log('file is completely uploaded!'); setTimeout(()=>{this.showfileuploaded='none';this.uploadPercent=0;},1000) console.log(event); (err)=>{ ()=>{ this.getFiles(); ) downloadTheFile=function(filename){ this._fileServ.deleteFile(filename).subscribe( console.log(file); for(leti=0;i<this.files.length;i++){ this.files.splice(i,1); } } ) } |
The Frontend part is completed, We will start the Backend, part.
create The main file server.js, files.js, and uploads folder.
server.js function.
2 4 6 8 10 12 14 16 18 20 22 24 26 28 | varpath=require('path'); varejs=require('ejs'); varapp=express(); app.set('views',path.resolve(__dirname,'../client/dist')); app.engine('html',require('ejs').renderFile); app.use(express.static(path.resolve(__dirname,'../client/dist'))); app.use(bodyParser.urlencoded({extended:true})); app.use(fileUpload()); varfiles=require('./files'); app.get('/*',(req,res)=>{ res.sendFile(path.resolve(__dirname,'../client/dist/index.html')); app.listen(port,function(){ }); |
files.js file.
require the important libs
![Download Download](/uploads/1/2/6/1/126153733/681292899.png)
2 4 | varmongojs=require('mongojs'); varpath=require('path'); |
initiate express router, current directory and connect to MongoDB database, We will use mlab.
2 4 | vardb=mongojs('mongodb://-----.mlab.com:41474/meanapp1',['files']); varDIR=path.resolve(__dirname,'uploads/'); |
Don’t forget to add your MongoDB database link.
the rest is routing functions to get all files, download and delete a file.
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 | console.log(req.files); let file=req.files.uploads, file.mv(path.resolve(DIR,filename),(err)=>{ console.log(err); else }); if(err)returnres.status(403).json({'result':'error','message':'something is wrong'}); console.log('file added to database'); }) }); router.get('/',(req,res)=>{ if(err) returnres.status(403).json({'result':'error','message':'something is wrong'}); returnres.send({'message':'success','files':files}); }); router.get('/:filename',(req,res)=>{ db.files.find({},(err,files)=>{ returnres.status(403).json({'result':'error','message':'something is wrong'}); varfilePath=path.resolve(DIR,req.params.filename); varmimetype=mime.lookup(path.resolve(DIR,req.params.filename)); }); router.delete('/:filename',(req,res)=>{ db.files.remove({$and:[{filename:req.params.filename}]},(err,file)=>{ returnres.status(404).json({'result':'error','message':'something is wrong'}); fs.unlink(path.resolve(DIR,req.params.filename),(err)=>{ }); }); |
files.js full code
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 | varmongojs=require('mongojs'); varpath=require('path'); varrouter=express.Router(); vardb=mongojs('mongodb://--------.mlab.com:41474/meanapp1',['files']); varDIR=path.resolve(__dirname,'uploads/'); router.post('/',(req,res)=>{ if(req.files){ filename=file.name; if(err){ } console.log('Done'); db.files.save({'filename':filename},(err,file)=>{ if(err)returnres.status(403).json({'result':'error','message':'something is wrong'}); console.log('file added to database'); }) }); router.get('/',(req,res)=>{ if(err) returnres.status(403).json({'result':'error','message':'something is wrong'}); returnres.send({'message':'success','files':files}); }); router.get('/:filename',(req,res)=>{ db.files.find({},(err,files)=>{ returnres.status(403).json({'result':'error','message':'something is wrong'}); varfilePath=path.resolve(DIR,req.params.filename); res.download(filePath,req.params.filename); }); db.files.remove({$and:[{filename:req.params.filename}]},(err,file)=>{ returnres.status(404).json({'result':'error','message':'something is wrong'}); fs.unlink(path.resolve(DIR,req.params.filename),(err)=>{ }); }); |
The result: