Unable to download file from retool storage programmatically

Hi @Dhivya,

You first need to set up a Retool Storage resource fetchFile and a variable fileIdVar.

On success add an event handler and add some js:

const fileData = fetchFile.data; // Get the query output
const base64Data = fileData?.base64Data; // Extract Base64 string
let fileName = fileData?.name || "downloaded_file.pdf"; // Extract filename
const fileType = fileData?.type || "application/pdf"; // Extract MIME type

// Extract only the file extension (e.g., "pdf" instead of "application/pdf")
const extension = fileType.split("/")[1]; // Gets "pdf"

// Check if fileName already has the correct extension
if (!fileName.toLowerCase().endsWith(`.${extension}`)) {
  fileName = `${fileName}.${extension}`;
}

if (!base64Data) {
  utils.showNotification({
    title: "Error",
    description: "File data is missing. Unable to download.",
    style: "error",
  });
} else {
  utils.downloadFile(
    { base64Binary: base64Data }, // Base64 data inside curly braces
    fileName // ✅ Remove `fileType` parameter to avoid double extensions
  );
}

Then in your button on click, run script to set your variable (getting the file id from the URL) and triggering fetchFile.

const fileUrl = table1.selectedRow?.file_url; // Get full file URL
const fileId = fileUrl?.split("/").pop(); // Extract last part (file ID)

if (!fileId) {
  utils.showNotification({
    title: "Error",
    description: "File ID is missing. Unable to fetch file.",
    style: "error",
  });
} else {
  console.log("Extracted File ID:", fileId); // Debugging
  fileIdVar.setValue(fileId); // ✅ Store fileId in the temporary state
  fetchFile.trigger(); // ✅ Trigger the query after setting the value
}

I have a working test app if you want to play around with it.

2 Likes