Can't upload files UAPI - Node.js

pqpier

Active Member
Aug 12, 2022
26
1
3
Brazil
cPanel Access Level
Root Administrator
Having a hard time with UAPI Functions - Fileman::upload_files

This is on front-end:
(...)
zip.generateAsync({type:"blob"}).then(async function(content) {
(...)
formData.append('my.zip', content);
const response = await api.post('/ul', formData);
(...)
}

This is on Node.js + express:
(...)
const zip = req.files['my.zip'].data

If I console.log(req.files['my.zip'])
{
name: 'blob',
data: <Buffer 50 4b 03 04 0a 00 00 00 00 00 0d 6d 48 55 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 6a 73 2f 50 4b 03 04 0a 00 00 00 00 00 0d 6d 48 55 00 00 00 ... 14279 more bytes>,
size: 14329,
encoding: '7bit',
tempFilePath: '',
truncated: false,
mimetype: 'application/zip',
md5: '3dccb4836924bcafa1a6a642ffa227b2',
mv: [Function: mv]
}
<Buffer 48 69 2c 20 4a 6f 75 72 6e 61 6c 44 45 56 20 55 73 65 72 73 2e 20 54 68 61 6e 6b 20 59 6f 75 2e>

If I console.log(zip):
<Buffer 50 4b 03 04 0a 00 00 00 00 00 c9 6c 48 55 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 6a 73 2f 50 4b 03 04 0a 00 00 00 00 00 c9 6c 48 55 00 00 00 ... 14279 more bytes>
<Buffer 48 69 2c 20 4a 6f 75 72 6e 61 6c 44 45 56 20 55 73 65 72 73 2e 20 54 68 61 6e 6b 20 59 6f 75 2e>

Then:
(...)
const form = new FormData();
form.append('dir', dir);
form.append('overwrite', 1);
form.append('file-1', zip, 'my.zip');

axios.post(url,
form,
{
headers: {
...form.getHeaders(),
'Authorization': accessToken
}
}).then(function (response) {
console.log('axios')
console.log(response.data);
}).catch(function(response){
console.log(response);
});

response.data is:
{
warnings: null,
status: 0,
errors: [ 'You must specify at least one file to upload.' ],
data: { warned: 0, uploads: [], succeeded: 0, failed: 0 },
messages: null,
metadata: {}
}

I tried every possible way. It always returns this "You must specify at least one file to upload".

What am I doing wrong here?
 

pqpier

Active Member
Aug 12, 2022
26
1
3
Brazil
cPanel Access Level
Root Administrator
Solved...

In case anyone ever stumbles upon this issue:
Use superagent library instead of axios.

In case anyone knows how to solve it without changing http library, let us humble mortals know.
 
  • Like
Reactions: cPRex

rbairwell

Well-Known Member
May 28, 2022
117
49
28
Mansfield, Nottingham, UK
cPanel Access Level
Root Administrator
I've not familiar with superagent or axios, but the HTML side of me is saying "content type missing" (i.e. in a HTML form you would include
enctype="multipart/form-data" , or use the header Content-Type: multipart/form-data ). If you try transmitting "files" without this, the uploads do get "confused" as the data block isn't properly separated from the file data.

What you might want to do during testing to see if this is the case (some HTTP libraries may automatically add the appropriate header), is to set your endpoint to something like Online API Testing Tool | Test Your API Online , RequestBin — A modern request bin to collect, inspect and debug HTTP requests and webhooks - Pipedream , httpbin.org PutsReq Webhook.site - Test, process and transform emails and HTTP requests etc so you can compare the full request being sent via both implementations and see what the difference is.
 

pqpier

Active Member
Aug 12, 2022
26
1
3
Brazil
cPanel Access Level
Root Administrator
Actually Content-Type multipart/form-data was there.

I think the issue is sending both "fields" and "files" in the same form. Because we have to pass field "dir" and also the file to be uploaded.

And I couldn't find a way for Axios to transmit it the right way, because everywhere they said I needed to add it like this:
formData.append("dir": dir)
formData.append("overwrite": 1)
formData.append("file-1", file, filename)

I also tried formData.append('file-1', file, {contentType: 'application/zip', filename: filename})

And cpanel API couldn't recognize the file.

But when using Requests library on Python, we have: requests.post(url, headers=headers, data=data, files=files)
Where Data is separate from Files.

And I think this is the reason why superagent also worked:
.post(url)
.auth(user, pwd)
.attach('file-1', zip, {filename: 'my.zip', contentType: 'application/zip'})
.field('dir', dir)
.field('overwrite', 1)
.then(res => console.log(res.text));

Where "dir" is added via field() method and file is added via attach() method.

So most probably has to do with Content Disposition and not Content-Type