Search code examples
javascriptnode.jsangularnestjs

Pass multipart form data from nest js server to another java server endpoint


I have a client-side application using Angular and server-side is Nest JS. I need to pass file data from client -> Nest JS -> Java end point (3rd party API).

How to pass buffered data from Nest JS server to Java end point

Here is my code

Client side

let fData: FormData = new FormData;
if(this.formService.model['uploadChecklist']) {
   fData.append('clientmanagedFacilityfile',this.formService.model['uploadChecklist']);
   fData.append('ticketID', this.ticketId);
   fData.append('employeeID', this.eid);
   this.gbtService.uploadtoNestJS(fData).subscribe((data) => {console.log(data)}) 
}

uploadtoNestJS(fData):Observable<any> {
        return this.http.post('/api/file/upload/newpoint',fData);
    }

Nest JS Server side

@Post('file/upload/newpoint')
    @UseInterceptors(FileInterceptor('clientmanagedFacilityfile'))
    uploadFile(@UploadedFile() clientmanagedFacilityfile, @Headers() headers,  @Body() body: {ticketID: string, employeeID: string}) {
        console.log(clientmanagedFacilityfile, '--------', headers, '--------', body.employeeID, body.ticketID); // Receiving all the values as expected 
        return this.fileService.uploadFiletoJava(clientmanagedFacilityfile,body,headers);
    }

uploadFiletoJava(files, bodyData: {ticketID: string, employeeID: string} , headers: Headers) {
console.log('----UPLOAD FILE TO JAVA END POINT----');
console.log(files, '------', headers)
const formData = new FormData(); 
formData.append(files.fieldname, files.buffer, files.originalname);
formData.append('ticketID', bodyData.ticketID);
formData.append('employeeID', bodyData.employeeID)
const baseApiUrl = 'https://api/v1.0.0/sendFileAttachment'
this.httpService.post(baseApiUrl, formData, {headers: headers}).pipe().toPromise();
}
  1. Is this my approach is right or wrong?
  2. uploadFiletoJava Do I need to convert again into formData

upload file to java end point

{
  fieldname: 'clientmanagedFacilityfile',
  originalname: 'Annamma-cough.pdf',
  encoding: '7bit',
  mimetype: 'application/pdf',
  buffer: <Buffer 25 50 44 46 2d 31 2e 34 0a 25 e2 e3 cf d3 0a 31 20 30 20 6f 62 6a 0a 3c 3c 2f 54 79 70 65 2f 58 4f 62 6a 65 63 74 2f 53 75 62 74 79 70 65 2f 49 6d 61 ... 763882 more bytes>,
  size: 763932
} ------ {
  'accept-language': 'en-US,en;q=0.9',
  'accept-encoding': 'gzip, deflate, br',
  referer: 'http://localhost:4200/send',
  'sec-fetch-dest': 'empty',
  'sec-fetch-mode': 'cors',
  'sec-fetch-site': 'same-origin',
  origin: 'http://localhost:4200',
  'sec-ch-ua-platform': '"Windows"',
  'source-id': 'abcder',
  'trace-id': '90f3d61e-xysde2-418f-b0e2-af90122621d7',
  uuid: '90f3d61e-xysde2-418f-b0e2-af90122621d7',
  'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36',
  accept: 'application/json',
  'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryUk4sy5LBUCZm8qkx',
  ......
 }

Solution

  • If the Node.js server gonna act like a proxy, and the goal is just to pass the data without any manipulations, then it wouldn't need to parse the incoming form-data/multipart request on the Node.js side.

    Hence, no need to use UploadedFile, and FileInterceptor decorators. Instead, we need to access raw request and response.

    /* or import from http if the target is based on HTTP */
    import { request} from 'https';
    import { Req, Res } from '@nestjs/common';
    import { Request, Response } from 'express';
    
    @Post('file/upload/newpoint')
    uploadFile(@Req req: Request, @Res res: Response) {
      const proxy = request(
        {
          hostname: <hostName>,
          port: <port>,
          method: 'post',
          path: <path>,
          headers: {
            'content-type': req.headers['content-type'],
            'content-length': req.headers['content-length'],
            // add any other headers as needed
          },
        },
        (resp) => {
          // pipe the target(i.e. Java server) response to client
          resp.pipe(res);
        },
      );
    
      // pipe incoming request to the target(i.e. Java server)
      req.pipe(proxy);
    }
    

    If you wouldn't want to send the Java response to the client, then remove resp.pipe(res), and add the following snippet:

    // ...
    req.on('end', () => {
       res.send(/* a response object */);
    });
    
    req.pipe(proxy);