Is it possible to send files through a form to a serverless function? Since you have to use ‘application/json’ as the content type and ‘multipart/form-data’ isn’t allowed data i don’t see a way to send it. But i might be wrong.
I actually figured it out by myself. You have to encode the file (for example an image) as a base64 string and put it in the JSON you are posting. You can decode the JSON on the serverless function using Buffer. https://www.pluralsight.com/guides/asynchronous-file-upload-react under “Uploading with JSON”.
Hi,
Just coming across this now and I’m having the same issue – are you able to share the code you’ve used to achieve this? I can get the file into my serverless function as base64, but am having trouble converting it back on the serverless side so it can be sent to the files API.
Cheers
having same trouble, do you have any solutions now?
Here is what I was able to get working.
I am encoding the file on the client then using buffer in the serverless function to convert it back to a file for sending to the hubspot API.
Client
async function uploadFile(file) {
async function uploadWithJSON() {
const toBase64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
const data = {
file: await toBase64(file),
name: file.name,
};
return JSON.stringify(data);
}
var requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: await uploadWithJSON(),
};
fetch('/_hcms/api/uploadLogo', requestOptions)
.then((response) => response.json())
.then((result) => {
console.log('result', result);
})
.catch((error) => console.log('error', error));
}
Severless Function
// Require axios library to make API requests
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
exports.main = (context, sendResponse) => {
// sendResponse({ body: { response: body }, statusCode: 200 });
const form = new FormData();
var fileOptions = {
access: 'PUBLIC_NOT_INDEXABLE',
overwrite: false,
duplicateValidationStrategy: 'NONE',
duplicateValidationScope: 'ENTIRE_PORTAL',
};
const buffer = Buffer.from(context.body.file.split(',')[1], 'base64');
form.append('file', buffer, context.body.name);
form.append('options', JSON.stringify(fileOptions));
form.append('folderPath', 'xxxxxxx');
var config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://api.hubapi.com/files/v3/files',
headers: {
Authorization: 'Bearer XXXXXXXXX',
...form.getHeaders(),
},
data: form,
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
sendResponse({ body: { response: response.data }, statusCode: 200 });
})
.catch(function (error) {
console.log(error);
sendResponse({
body: { errormsg: error.message },
statusCode: 500,
});
});
};
Hey, @DHolland Thank you very much for taking the time to come back and share what worked for you. — Jaycee
Hey, sorry for not answering before, didnt see the email.
It has been some time since I did this, so i cant really recollect if i even continued that route I was asking here. But i can share the code i used to process an image and send it to another api. I didnt use the Files api though, it is a third party api, that has nothing to do with hubspot. Here is the serverless function:
const axios = require("axios");
const FormData = require('form-data');
exports.main = (context, sendResponse) => {
sendForm(context).then((data) => {
if (!data.response) {
sendResponse({
body: 'candid({response: "success ' + data.status + ' ' + data.statusText + '"})',
statusCode: 200
});
} else {
console.log("error");
sendResponse({
body: data.response.data,
statusCode: data.response.status
});
}
});
};
function baseToFile(theBlob, fileName){
if (theBlob !== "") {
let remainder = theBlob.split(",")[1];
let buf;
buf = Buffer.from(remainder, 'base64');
buf.lastModifiedDate = new Date();
buf.name = fileName;
return buf;
} else {
return "";
}
}
async function sendForm(context) {
try {
const form = new FormData();
var myFile0 = baseToFile(context.body.File0, context.body.File0Name);
var myFile1 = baseToFile(context.body.File1, context.body.File1Name);
var myFile2 = baseToFile(context.body.File2, context.body.File2Name);
form.append('File0', myFile0);
form.append('File1', myFile1);
form.append('File2', myFile2);
const response = await axios.post('API_URL', form, {
headers: form.getHeaders()
});
return response;
} catch (error) {
return error;
}
}
I guess what you are asking for is in the blobToFile() method.