0

I am trying to upload the file by web browser but i can't do that. When i save this api by postman then uploaded the file but i can't upload the file by trying web browser. When i try to upload the file by web browser then I got an error like "SyntaxError: Unexpected token - in JSON at position 0" in my server side.

I am using NodeJS, ExpressJs as a back-end and Angular 6 as a front-end.

Angular

html

<div>
  <div>
    <input type="file" (change)="createFormData($event)">
  </div>
  <button (click)="upload()">Upload</button>
</div>

ts

export class PhotographComponent implements OnInit {
  selectedFile: File = null;
  fd = new FormData();

  constructor(private formBuilder: FormBuilder, private httpClient: 
  HttpClient) {}

  ngOnInit() {}

  createFormData(event) {
    this.selectedFile = <File>event.target.files[0];
    this.fd.append('photo', this.selectedFile, this.selectedFile.name);
  }

  upload() {
    this.httpClient.post(environment.apiUrl + 'photographs', this.fd)
      .subscribe( result => {
        console.log(result);
      });
  }

}

NodeJs

const { Photograph, validate } = require('../models/photograph');
const multer  = require('multer');
const express = require('express');
const router = express.Router();

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'uploads')
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname)
    }
})

const upload = multer({
    storage: storage
})

// save photograph
router.post('/', upload.single('photo'), (req, res) => {
    console.log(req.file);
    const filename = req.file.filename;
    const path = req.file.path;

    res.json({message: 'File uploaded'});
})

module.exports = router;

Please help me to find a solution to upload a file. Thanks.

Monir Tuhin
  • 107
  • 1
  • 11
  • Does this error happen on server side? Also what size file you're uploading is? – Evaldas Buinauskas Aug 20 '19 at 12:20
  • Yes . When i save this api by postman then uploaded the file but i can't upload the file by trying web browser. When i try to upload the file by web browser then I got an error like "SyntaxError: Unexpected token - in JSON at position 0" in my server side. – Monir Tuhin Aug 20 '19 at 12:32
  • My file size only 45kb – Monir Tuhin Aug 20 '19 at 12:33
  • Have you tried explicitly setting the request header on the client side to have `enctype: multipart/form-data`? – Andy Aug 20 '19 at 12:44
  • No i don't. I have set the header ('Content-Type': 'application/json') in Auth Intercepter – Monir Tuhin Aug 20 '19 at 12:50
  • How to set the header "enctype: multipart/form-data" in my angular http function – Monir Tuhin Aug 20 '19 at 12:51
  • Take a look at [here](https://stackoverflow.com/questions/50572363/angular-6-post-request-with-a-multipart-form-doesnt-include-the-attached-file-o/50572596). Should be as simple as `this.httpClient.post(environment.apiUrl + 'photographs', this.fd, HttpUploadOptions)` – Andy Aug 20 '19 at 12:59
  • const HttpUploadOptions = { headers: new HttpHeaders({ "Content-Type": "multipart/form-data" }) } this.httpClient.post(environment.apiUrl + 'photographs', this.fd, HttpUploadOptions) i have tried these but in browser network shows me auth intercepter's 'Content-Type': 'application/json'. – Monir Tuhin Aug 20 '19 at 13:41
  • How to explicitly add header in request in angular though have auth interceptor's header – Monir Tuhin Aug 20 '19 at 13:42

3 Answers3

1

Actually i have found my solution. My back-end (NodeJs) code was right. I have modified my front-end(Angular) with some changes.

Angular

html

<input id="photo" type="file" />

<button type="button" (click)="upload()">
  Upload
</button>

ts

upload() {
let inputEl: HTMLInputElement = this.el.nativeElement.querySelector('#photo');
console.log("iam+ " + inputEl);
let fileCount: number = inputEl.files.length;
let formData = new FormData();
if (fileCount > 0) { // a file was selected
  for (let i = 0; i < fileCount; i++) {
    formData.append('photo', inputEl.files.item(i));
  }

  this.httpClient.post(URL, formData)
    .subscribe((res) => {
        console.log('Upload Success');
      },
      msg => {
        console.error(`Error: ${msg.status} ${msg.statusText}`);
      }
    );
  }

}
Community
  • 1
  • 1
Monir Tuhin
  • 107
  • 1
  • 11
0

Add 'Accept': 'application/json' in the request header at client side.

private getHeaders() {
    const headers = new HttpHeaders({
      'Accept': 'application/json',
    });
    return headers;
  }
    upload() {
        this.httpClient.post(environment.apiUrl + 'photographs', this.fd,{ headers: this.getHeaders() })
          .subscribe( result => {
            console.log(result);
          });
      }

And in Nodejs application add 'Accept' in response header at middleware

    app.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization, PublicKey"
    );
    next();
});
0

It seems like you are facing httpInterceptor issue, I also have faced the same issue, you can overwrite the httpInterceptor or create new httpClient.

This may help you:

export class PhotographComponent implements OnInit {
  private customHttpClient: HttpClient;
  selectedFile: File = null;
  fd = new FormData();

  constructor(private formBuilder: FormBuilder, private httpClient: 
  HttpClient, private handler: HttpBackend) {
     this.customHttpClient = new HttpClient(handler);
  }

  ngOnInit() {}

  createFormData(event) {
    this.selectedFile = <File>event.target.files[0];
    this.fd.append('photo', this.selectedFile, this.selectedFile.name);
  }

  upload() {
     const httpOptions = {
         headers: new HttpHeaders({
         'Accept': 'application/json',
         //'Authorization': 'Bearer '+ token,
       })
     };

    this.customHttpClient.post(environment.apiUrl + 'photographs', this.fd, httpOptions )
      .subscribe( result => {
        console.log(result);
      });
  }

}
Md Alamin
  • 1,084
  • 11
  • 19