Search code examples
node.jsangularexpressfile-uploadmulter

How to upload files using Angular 2+ , Express and nodeJs


Im trying to upload an image using Angular 4, node and Express with the Multer library.

here is my route.js :

const storage = multer.diskStorage({
destination: function(req, file, cb) {
    cb(null, 'uploads')
},
filename: function(req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now() + '.jpg')
   }
});

const upload = multer({ storage: storage }).single('avatar');


router.post('/upload_avatar', function(req, res) {
upload(req, res, function(err) {
    if (err) {
        // An error occurred when uploading
        throw err;
    }
    res.json({
        sucess: true,
        message: 'Image was uploaded successfully'
    });
    // Everything went fine
  })
});

if i use Postman it does work and adds the image into the uploads directory in my project.

here is my UserService.js

import { Injectable } from '@angular/core';
import {Http, Headers, RequestOptions} from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class UserService {
  user: any;
  filesToUpload: Array<File> = [];

  constructor(private http: Http) { }

  uploadAvatar(event){
   let fileList: FileList = event.target.files;
   if(fileList.length > 0) {
    let file: File = fileList[0];
    let formData:FormData = new FormData();
    formData.append('uploadFile', file, file.name);
    let headers = new Headers();
    /** No need to include Content-Type in Angular 4 */
    // headers.append('Content-Type', 'multipart/form-data');
    // headers.append('Accept', 'application/json');

     this.http.post('http://localhost:3000/api/upload_avatar', formData, 
     {headers: headers})
        .map(res => res.json())
        .catch(function(err){
          throw err;
        })
        .subscribe(
            data => console.log('success'),
            error => console.log(error)
        )
  }
}

and my profile.component.ts uses this function :

 fileChangeEvent(event) {
 this.userService.uploadAvatar(event); 
}

finally my HTML looks like this :

<div class="col-md-4">
            <img [src]="userImg" class="img-thumbnail" alt="">
            <input type="file" (change)="fileChangeEvent($event)" 
placeholder="Upload file..." />
            <!-- <button type="button" (click)="upload()">Upload</button> --
>
        </div>

when i use postman it works, so i guess the problem has to do with angular code. also i think it has to be with headers or body request. here is the error i get from node server :

      C:\Users\admin\Desktop\project\contactlist\routes\route.js:33
        throw err;
        ^
       Error: Unexpected field
       at makeError 

 node_modules\multer\lib\make-
  error.js:12:13)
  at wrappedFileFilter 
 node_modules\multer\index.js:40:19)
  at Busboy.<anonymous> \node_modules\multer\lib\make-middleware.js:114:7)
  at emitMany (events.js:127:13)
 at Busboy.emit (events.js:201:7)
  at Busboy.emit node_modules\busboy\lib\main.js:38:33)
at PartStream.<anonymous> ( 
node_modules\busboy\lib\types\multipart.js:213:13)
at emitOne (events.js:96:13)
at PartStream.emit (events.js:188:7)
at HeaderParser.<anonymous> (node_modules\dicer\lib\Dicer.js:51:16)
at emitOne (events.js:96:13)
at HeaderParser.emit (events.js:188:7)
at HeaderParser._finish (node_modules\dicer\lib\HeaderParser.js:68:8)
at SBMH.<anonymous> (node_modules\dicer\lib\HeaderParser.js:40:12)
at emitMany (events.js:127:13)
at SBMH.emit (events.js:201:7)

Solution

  • just changed this line from :

    formData.append('uploadFile', file, file.name);
    

    to:

    formData.append('avatar', file, file.name);
    

    now it works !