I’m trying to upload a file to an endpoint with Axios but I keep getting a 400 error ‘Uploaded file is empty’.
The file is not empty at all – it is around 90MB.
When I upload to the same endpoint with Postman it all works flawlessly. Indeed it used to work flawlessly via the code but for some reason it has started to fail.
Here is the code:
async function uploadMediaToSermonAudio(URL, filePath) {
console.log('File Path: ', filePath)
const file = fs.createReadStream(filePath)
const response = await axios.post(URL, file);
if (response.status === 201) {
console.log('Media uploaded!');
data = response.data;
console.log('Data: ', data)
return true;
} else {
console.error('Media not uploaded:', response.statusText);
return false;
}
}
On further investigation, it looks like something to do with the function that downloads the file from Google Drive. When I download manually, the upload is then successful.
Strangely, there doesn’t seem to be anything wrong with the file downloaded through Node – it plays back without a hitch.
Here is the function to get the file in the first place:
async function getDriveFile(auth, fileName, folderId) {
const drive = google.drive({ version: 'v3', auth });
// Recursive search to find the file in the folder or its subfolders
async function findFileInFolder(folderId) {
// Search for the file in the current folder
const res = await drive.files.list({
q: `name='${fileName}' and '${folderId}' in parents and trashed=false`,
fields: 'files(id, name, mimeType)',
});
if (res.data.files.length > 0) {
return res.data.files[0]; // Return the first match
}
// If the file is not found, search in subfolders recursively
const subfolders = await drive.files.list({
q: `'${folderId}' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false`,
fields: 'files(id, name)',
});
for (const folder of subfolders.data.files) {
const foundFile = await findFileInFolder(folder.id);
if (foundFile) {
return foundFile;
}
}
return null; // If no file is found in this folder or its subfolders
}
// Start the search in the provided shared folder
const file = await findFileInFolder(folderId);
if (!file) {
throw new Error(`File not found: ${fileName}`);
}
// Download the file as a temporary file in the container
const filePath = path.join('/tmp/', file.name.toLowerCase());
const dest = fs.createWriteStream(filePath);
await drive.files.get(
{ fileId: file.id, alt: 'media' },
{ responseType: 'stream' },
function (err, res) {
if (err) {
throw err;
}
res.data.pipe(dest);
}
);
return filePath;
}
2
Fixed it!
I modified the pipe call in the getDriveFile function to include a finish callback:
const promise = new Promise((resolve, reject) => {drive.files.get(
{ fileId: file.id, alt: 'media' },
{ responseType: 'stream' },
function (err, res) {
if (err) {
reject(err);
}
res.data.pipe(dest).on('finish', () => {resolve(filePath)});
}
);});
promise.then((res) => {
})
.catch((e) => {
console.log(e);
});
return promise;