1

I'm currently making a simple function that creates a Form Data, append necessary variables then send it to an external server. This server receives variables listed in form.append and one of those variables requires an image file to be sent. Here's my code:

router.get('/test-poster',upload.any(), async (req, res) => {

const form = new FormData();
form.append("file", fs.createReadStream('../../backendsmartattendance/backend_server/uploads/tmp/image.jpg'), {
    contentType: 'image/jpeg',
    filename: 'image.jpg',
    });
form.append("phone", '085273396452');
form.append("message", 'This is a test message');
form.append("token", 'LQanvrN2EkDp3mQWy')

axios.post(`https://api.sparks.id/api/whatsapp/image`, form, { 
    headers: {
        'Content-Type': 'application/json' 
    }
})
.then(()=>{
    return res.status(200).json({code:200,status:true,message:'Data successfully sent'});
})
.catch((error)=>{
    return res.status(500).json({code:500,status:false,message:error});
})
})

When I run it, I get an error "Request failed with status code 415" which I assume is because the server does not accept my format, but I'm not sure of why exactly the server rejects it. I firstly thought I didn't send the image file, so I tried to send a request without the 'file' field in the formData, this still results in the same error code. Then I thought the server maybe only accepts an object instead of a formData (which was specifically said in documentation it only accepts formData) and of course it still results in the same error code. I have no idea what causes this problem and I'm pretty new on how to properly send node http requests, so any help will be highly appreciated.

===

Update

Thank your for the people that helped giving me inputs, its really helpful and my code has worked on sending the file but it seems like the format is not what the server expect. I've read the server's documentation and it give an example in curl like this to send a file:

curl -X 'POST' 'https://api.sparks.id/api/whatsapp/image' -F 'file=@245907736_1159912484416576_7427838087540430398_n.jpg;type=image/jpeg'

And so I tried to send the file in a formData like this:

const form = new FormData();
form.append("file", fs.readFileSync('../../backendsmartattendance/backend_server/uploads/tmp/image.jpg'), {
    contentType: 'image/jpg',
    filename: 'image.jpg',
    });
axios.post(`https://api.sparks.id/api/whatsapp/image`, data, {
        headers:{
            "Accept": 'application/json',
            "Content-Type":"multipart/form-data"
        }
    })
    .then((resp)=>{
        return res.status(200).json({code:200,status:true,message:'Data successfully sent'});
    })
    .catch((error)=>{
        return res.status(500).json({code:500,status:false,message:error});
    })

But it doesn't work (still returns error code 422: The given data is invalid/wrong format), I'm quite confused because isn't this how you're supposed to send the image in the formData? Or have I convert the curl syntax wrong?

Zero Gear
  • 53
  • 7
  • `fs.createReadStream` returns `FileStream` instead of actually file, so you need read file via stream before adding them into the form data. Alternative solution: use [fs.readFile](https://nodejs.org/api/fs.html#fsreadfilepath-options-callback) or [fs.readFileSync](https://nodejs.org/api/fs.html#fsreadfilesyncpath-options) instead. Or you even can send request data as `JSON` with file encoded as `base64` if API accept `JSON`. – Xeelley Nov 19 '21 at 08:10
  • thank you for your response, i've tried your solution by using the fs.readFile instead of fs.createReadStream and it worked. there is other problem however, because the server send back an error "Request failed with status code 422" which from my quick searching is because the server don't understand what to do with data given to it which is funny because i tried sending a request from post man (https://i.ibb.co/hHC7LdR/image.png) and it succeed. does this mean my code doesn't send the same data and format like the postman does? – Zero Gear Nov 19 '21 at 08:33
  • Compare file encoding between your code and postman request. Issue may be caused because of wrong file encoding (usually `base64` accepted) or wrong/missing headers. – Xeelley Nov 19 '21 at 08:36
  • Also should be noticed both `readFile` methods (sync / async) return `Buffer`, so when you add it into form data, NodeJS converts it to string automatically. [Buffer.toString](https://nodejs.org/api/buffer.html#buftostringencoding-start-end) encoding buffer as 'UTF8' by default. – Xeelley Nov 19 '21 at 08:38
  • Thank you for your help, appreciate it a lot. I'm still a bit confused on how to properly send this file though.. Because the server only says to format the data as a 'string($int64)' and the example it gives in the documentation is in curl like the update I just posted. Do you have any input about this one? – Zero Gear Nov 23 '21 at 05:05
  • Hmmm, it's kinda strange because code you wrote should work. I can suggest you to use [restler](https://www.npmjs.com/package/restler) for this kind of requests or looks here: https://stackoverflow.com/questions/47630163/axios-post-request-to-send-form-data – Xeelley Nov 23 '21 at 07:46

0 Answers0