I was working on testing upload images to Cloudflare using their API. The task was supposed to be simple because cloudfare have some code samples here, however I was having trouble getting it to work. As I’m using node+axios , the sample code on document is like
var axios = require("axios").default;
var options = {
method: 'POST',
url: 'https://api.cloudflare.com/client/v4/accounts/account_identifier/images/v1',
headers: {
'Content-Type': 'multipart/form-data; boundary=---011000010111000001101001',
'X-Auth-Email': ''
},
data: '...'
};
axios.request(options).then(function (response) {
console.log(response.data);
}).catch(function (error) {
console.error(error);
});
The problem is it doesn’t say how to build this data string, initially I (OK I confess it was from gpt) build the request method like
const imageBinary = fs.readFileSync(imagePath);
formData.append('file', imageBinary);
const headers = {
Authorization: `Bearer ${apiToken}`,
'Content-Type': `multipart/form-data; boundary=${formData_boundary}`,
};
const response = await axios.post(
`https://api.cloudflare.com/client/v4/accounts/${accountId}/images/v1`,
formData,
{ headers }
);
It returned a 415 error, and the detail is “‘ERROR 5455: Uploaded image must have image/jpeg, image/png, image/webp, image/gif or image/svg+xml content-type\n”
I natually thought it was a file format problem, however I checked it was a png file, I even used a jpeg file for test, still got the same.
I then tried to use readFileStream and readFile in promise way, still got the same error.
Then I checked https://developer.mozilla.org/en-US/docs/Web/API/FormData/append and found that I can give it a third parameter to specify the filename although it’s optional, but worth a try, so I changed the code to
formData.append('file', imageBinary, 'test.png');
Then I got error " TypeError: Failed to execute ‘append’ on ‘FormData’: parameter 2 is not of type ‘Blob’"
So what is Blob? I checked https://developer.mozilla.org/en-US/docs/Web/API/Blob and found that it is a file-like object, anyway coplilot had already given me a hint, so I changed the code to
const blobImage = new Blob([imageBinary.buffer]);
formData.append('file', blobImage, 'test.png');
and it finally worked!
So the final code is like
const imageBinary = fs.readFileSync(imagePath);
const formData = new FormData();
const blobData = new Blob([imageBinary.buffer]);
formData.append("file", blobData, "test.png");
const headers = {
Authorization: `Bearer ${apiToken}`,
"Content-Type": `multipart/form-data; boundary=${formData._boundary}`,
};
const response = await axios.post(
`https://api.cloudflare.com/client/v4/accounts/${accountId}/images/v1`,
formData,
{ headers }
);
My speculation based on my limited node experince is that if you pass two parameters to formdata.append, the second parameter would be considered a String. While on cloudflare’s end, it requires you to specify the file type , so you have to pass some parameter to tell it.
I wish cloudflare could have given a more detailed example, but anyway I hope this can help someone who is having the same problem.