is there a way to convert a binary file which I’ve retrieved inside a Action Button Script using the Fibery File API to a Base64 format, also inside the same Script?
Or, another option for me, would be to send this binary file through the http.postAsync using a “multipart/form-data” content-type
See the two options bellow, please
// OPTION 1 - send a binary file to a external API using a multipart/form-data Content-type
for (const file of files['Files']) {
const fileWithSecret = await fibery.getEntityById("fibery/file", file['id'], ["Secret", "Name", "Content Type"]);
const fileUrl = "http://<mydomain>.fibery.io/api/files/" + fileWithSecret["Secret"];
const f = await http.getAsync(fileUrl, { 'headers': { 'Authorization': 'Token mytoken' } });
// here is the external API to where I need to send the file
const responseArquivo = await http.postAsync('https://myexternalapi', {
body: // HOW DO I PASS multipart/form-data HERE? ... let's say I have two keys here: file_name and file (the binary itself)
,
headers: {
'Content-type': 'multipart/form-data',
'apikey': 'xxxxx'
}
});
}
// OPTION 2 - send a BASE64 to a external API using a application/json Content-type
for (const file of files['Files']) {
const fileWithSecret = await fibery.getEntityById("fibery/file", file['id'], ["Secret", "Name", "Content Type"]);
const fileUrl = "http://<mydomain>.fibery.io/api/files/" + fileWithSecret["Secret"];
const f = await http.getAsync(fileUrl, { 'headers': { 'Authorization': 'Token mytoken' } });
// here is the external API to where I need to send the file
const responseArquivo = await http.postAsync('https://myexternalapi', {
body: {
filename: fileWithSecret["Name"],
file: // HERE I NEED A BASE64 string representation of the file
}
,
headers: {
'Content-type': 'application/json',
'apikey': 'xxxxx'
}
});
}
the function btoa does not exist in the reduced Fibery sandbox environment for the Script action. An alternative is the Buffer.from function available in Node, however the Buffer keyword is also not part of the Fibery script environment. You therefore have to paste the following code into your script action, which implements base64 encoding from scratch.
I took it from an npm package and adjusted it so that it can run inside the Fibery Script action:
const base64Characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
function textToBinary(text) {
let binaries = "";
for (let i = 0; i < text.length; i++) {
const letterBinary = text.charCodeAt(i).toString(2);
const letterBinary8Bits = letterBinary.padStart(8, "0");
binaries += letterBinary8Bits;
}
return binaries;
}
function groupBinariesByNumberOfBits(binary, quantityOfBits) {
const regex = new RegExp(`.{1,${quantityOfBits}}`, "g");
const groupedBinaries = binary.match(regex);
const binariesWithQuantityOfBits = groupedBinaries.map((binary) =>
binary.padEnd(quantityOfBits, "0")
);
return binariesWithQuantityOfBits;
}
function binaryToDecimal(binary) {
const decimal = parseInt(binary, 2);
return decimal;
}
function binaryToBase64(binary) {
const groupedBinaries = groupBinariesByNumberOfBits(binary, 6);
const base64 = groupedBinaries.map((binary) => {
const decimal = binaryToDecimal(binary);
return base64Characters[decimal];
});
const base64ArrayAsString = base64.join("");
return base64ArrayAsString;
}
function addEndChar(text, base64) {
const remainderMultipleOf3 = {
0: "",
1: "==",
2: "=",
};
const remainder = text.length % 3;
const base64WithEndChar = base64.concat(remainderMultipleOf3[remainder]);
return base64WithEndChar;
}
function base64Encode(text) {
if (!text) return text;
let data = "";
data = text;
const binary = textToBinary(data);
const base64 = binaryToBase64(binary);
const base64WithEndChar = addEndChar(data, base64);
return base64WithEndChar;
}
// Example: this correctly prints 'dGVzdA=='
console.log(base64Encode("test"));
You can now use the function base64Encode to base64 encode any string inside your Script action
Hi there @derbenoo … thanks a lot for your attention on this.
Sorry for the delayed answer, got some other issues here and only now I’m returning on this.
I’ve tested the script you’ve shared and it works well with text data .
But I’m downloading a binary file, like in the code below.
I’ve also tested with others scripts I’ve found on the internet that deals with binary ones. It didn’t work too. I’m suspecting the function “await http.getAsync(fileUrl, { ‘headers’: { ‘Authorization’: ‘Token mytoken’ } });” is somehow messing the content up before returning the result, perhaps forcing it to a string type. I’m not sure. I couldn’t figure it out.
for (const entity of args.currentEntities) {
try {
const files = await fibery.getEntityById(entity.type, entity.id, ['Files']);
for (const file of files['Files']) {
const fileWithSecret = await fibery.getEntityById("fibery/file", file['id'], ["Secret", "Name", "Content Type"]);
const fileUrl = "http://mydomain.fibery.io/api/files/" + fileWithSecret["Secret"];
// download file (perhaps here the things are getting wrong)
const f = await http.getAsync(fileUrl, { 'headers': { 'Authorization': 'Token mytoken' } });
const base64EncodedFile = base64Encode(f) // here your original function expects a text instead of a binary
//console.log(['tipo', Object.prototype.toString.call(f)]);
console.log(['File in b64', base64EncodedFile]);
}
} catch (e) {
console.error(e)
throw (e)
}
}
Please double check the type of the return value from http.getAsync(), so you know exactly what you’re dealing with – e.g. is it a String, ArrayBuffer, etc.