0

I'm trying to send an Image to Node via Angular 5 the problem that i have is, when i try it , Angular send an empty Json file

This is the HTML5 code :

<input (change)="onFileSelected($event)" type="file" class="custom-file-input" name="file" id="file" accept="image/gif, image/jpg,  image/jpeg" >
<button type="button" (click)="onUpload()" class="btn btn-info btn-block">upload</button>

This is the code in component.ts

onFileSelected(event){
  this.selectedFile = event.target.files[0];
  console.log(event);
}
onUpload(){
  const fd = new FormData();
  fd.append('file',this.selectedFile, this.selectedFile.name);
  this.authService.onUpload(fd).subscribe(data=>{
    if(!data.success){
      this.messageClass = 'alert alert-danger'; // Set bootstrap error class
      this.message = data.message; // Set error message
      console.log(data.message);
    }else{
      this.messageClass = 'alert alert-success'; // Set bootstrap error class
      this.message = data.message; // Set error message
      console.log('it worked');
    }
  });

}

When i upload the file without the headers and dispelling the back-end checker it work it but I required a kind of authorization to the requests so it need a token file

The code of the Token creation

// Function to create headers, add token, to be used in HTTP requests
  createAuthenticationHeaders() {
    this.loadToken(); // Get token so it can be attached to headers
    // Headers configuration options
    this.options = new RequestOptions({
      headers: new Headers({
        'Content-Type': 'application/json', // Format set to JSON
        'authorization': this.authToken // Attach token
      })
    });
  }

loadToken() {
  this.authToken = localStorage.getItem('token'); // Get token and asssign to variable to be used elsewhere
}

The code of the service

// Function to get user's upload image
  onUpload(fd){
    this.createAuthenticationHeaders(); // Create headers before sending to API
    return this.http.post(this.domain + '/authentication/profileImage',fd , this.options).map(res => res.json());
  }

So now whenever I make a request it turn in to a Json how i can make it as a file type

I create a new function and changed the Content-Type

createAuthenticationHeadersForFiles() {
    this.loadToken(); // Get token so it can be attached to headers
    // Headers configuration options
    this.option = new RequestOptions({
      headers: new Headers({
        'Content-Type': 'application/form-data', // Format set to FormData
        'authorization': this.authToken // Attach token
      })
    });
  }

  // Function to get token from client local storage
loadToken() {
  this.authToken = localStorage.getItem('token'); // Get token and asssign to variable to be used elsewhere
} 

but it didn't work as expected, it couldn't save the image

The back-end code using Node

/* ===============================================================
     Route to post user's profile image
  =============================================================== */
  // init gfs
  let gfs;
  const conn = mongoose.createConnection('mongodb://localhost:27017/zaad');
  conn.once('open',()=>{
    gfs = Grid(conn.db,mongoose.mongo);
    gfs.collection('profileImages');
  });

  const storage = new GridFsStorage({
    url:config.uri,
    file:(req,file)=>{
      return new Promise((resolve,reject)=>{
        crypto.randomBytes(16,(err,buf)=>{
          if(err){
            return reject(err);
          }
          const filename = buf.toString('hex')+ path.extname(file.originalname);
          const fileinfo = {
            filename:filename,
            bucketName:'profileImages'
          };
          resolve(fileinfo);
        });
      });
    }
  });

  const upload = multer({storage});
  router.post('/profileImage',upload.single('file'),(req,res)=>{
    if(!req.file){
      res.json({success:false , message:'no image was provided'});
    }else{

      res.json({file:req.file});
    }
  });

Then with the devtool from Chrome i try to analysis the request and this the result

General:
Request URL: http://localhost:8080/authentication/profileImage
Request Method: POST
Status Code: 200 OK
Remote Address: [::1]:8080
Referrer Policy: no-referrer-when-downgrade
Response Headers:
Access-Control-Allow-Origin: http://localhost:4200
Connection: keep-alive
Content-Length: 51
Content-Type: application/json; charset=utf-8
Date: Sat, 26 May 2018 11:17:16 GMT
ETag: W/"33-cBZTT/RGV75GPZIbsrhHP7Mg3SM"
Vary: Origin
X-Powered-By: Express
Request Headers:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: ar,en-US;q=0.9,en;q=0.8,fr;q=0.7
authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1YWYzZDM4ZWE1MWM0ZjMxNzhlYWFkN2QiLCJpYXQiOjE1MjczMzI3NzksImV4cCI6MTUyNzQxOTE3OX0.78SoKSz5KlIQB-sh3oZjrfiot9cFLUuH79Q-DgRmSag
Connection: keep-alive
Content-Length: 763935
Content-Type: application/form-data
Host: localhost:8080
Origin: http://localhost:4200
Referer: http://localhost:4200/edit-profile/5af3d38ea51c4f3178eaad7d
User-Agent: Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
Request Payload:
------WebKitFormBoundaryUq12HhowsrOlY9bF
Content-Disposition: form-data; name="file"; filename="erp-img.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryUq12HhowsrOlY9bF--
Hathefah Al-Sharami
  • 163
  • 1
  • 3
  • 11

1 Answers1

0

The issue seems to be in the "createAuthenticationHeaders()" function. In this function you are setting Content-Type to "application/json" instead set it to "multipart/form-data" OR "application/form-data" (whichever works for you), so that your updated createAuthenticationHeaders() method would be :-

  createAuthenticationHeaders() {
    this.loadToken(); // Get token so it can be attached to headers
    // Headers configuration options
    this.options = new RequestOptions({
      headers: new Headers({
        'Content-Type': 'application/form-data', // or any other appropriate type as per requirement
        'authorization': this.authToken // Attach token
      })
    });
  }

-----------------------------EDIT------------------------

Since your request payload is showing :-

    ------WebKitFormBoundaryUq12HhowsrOlY9bF
Content-Disposition: form-data; name="file"; filename="erp-img.jpg"
Content-Type: image/jpeg

That means client side is working fine. The problem is on server side.

Yatharth Varshney
  • 1,973
  • 20
  • 22
  • Since your request payload is showing :- ------WebKitFormBoundaryUq12HhowsrOlY9bF Content-Disposition: form-data; name="file"; filename="erp-img.jpg" Content-Type: image/jpeg That means the client side is working fine. The problem must be on server side. – Yatharth Varshney May 26 '18 at 11:54
  • i tried making the same back- end but with out the authorization and it worked so the problem now that when the Angular send the file with the authorization it doesn't send it as req.file – Hathefah Al-Sharami May 27 '18 at 07:23