Issue uploading file on iOS and macOS

I have developed a plugin to upload multiple files to the Bubble server. It works great on other devices except for iOS and MacOS. It works on Chrome but not on Safari. The issue that I think it is having is due to the WebKit engine Apple uses for its browsers.

Here is the code for the action that is responsible for uploading file to bubble:
function(instance, properties, context) {
if (instance.data.nomes.length > 0) {
const extensoes = instance.data.extensoes;
const nomes = instance.data.nomes;
const totalFiles = instance.data.nomes.length;

    let uploadedFiles = [];
    let totalBytes = 0;
    let uploadedBytes = 0;

    // Calculate total bytes for all files
    instance.data.size.forEach((fileSize) => {
        totalBytes += fileSize;
    });

    // Function to update progress
    function updateProgress(bytesUploaded) {
        uploadedBytes += bytesUploaded;
        const progress = (uploadedBytes / totalBytes) * 100;
        console.log("Update Progress");
        instance.publishState('progress', progress.toFixed(2));
    }

    // Function to upload a single file with granular progress updates
    function uploadFile(index) {
        return new Promise((resolve, reject) => {
            // Offload base64 to Blob conversion to avoid blocking the main thread
            setTimeout(() => {
                const name = nomes[index].split('.').slice(0, -1).join('.');
                const extension = extensoes[index];
                const fileName = `${name}.${extension}`;

                // Convert Blob to byte array (no base64)
                instance.data.blob[index].arrayBuffer().then(arrayBuffer => {
                    const byteArray = new Uint8Array(arrayBuffer);
                    console.log(byteArray); // Logs the byte array

                    const blob = new Blob([byteArray], { type: 'application/octet-stream' });
                    const file = new File([blob], fileName);
                    const fileSize = instance.data.size[index]; // Get the size for the specific file
                    let uploadedForThisFile = 0; // Bytes uploaded for this file

                    // Check if file can be uploaded
                    if (!instance.canUploadFile(file)) {
                        reject(new Error("File cannot be uploaded. Check the size or other constraints."));
                        return;
                    }

                    // Start file upload using instance.uploadFile
                    instance.uploadFile(
                        file,
                        function (err, url) {
                            if (err) {
                                reject(err);
                                return;
                            }

                            if (url) {
                                updateProgress(fileSize - uploadedForThisFile);
                                uploadedFiles.push(url);
                                resolve();
                            }
                        },
                        properties.attachTo, // Optional parameter for attaching to a thing
                        function (progress) {
                            const progressIncrement = progress * fileSize - uploadedForThisFile;
                            if (progressIncrement > 0) {
                                updateProgress(progressIncrement);
                                uploadedForThisFile += progressIncrement;
                            }
                        }
                    );
                }).catch(err => {
                    console.error('Error converting Blob to ArrayBuffer:', err);
                    reject(err);
                });
            }, 0); // Delay conversion to prevent blocking the UI
        });
    }

    // Upload all files sequentially
    async function uploadAllFiles() {
        try {
            for (let i = 0; i < totalFiles; i++) {
                await uploadFile(i); // Wait for each file to complete
            }

            // All files uploaded
            instance.publishState('bubble', uploadedFiles);
            instance.triggerEvent('saved'); // Trigger save event
        } catch (err) {
            console.error("File upload error:", err);
        }
    }

    // Start uploading
    uploadAllFiles();
} else {
    console.warn("No files to upload.");
}

}
Just want to specify that I am using blobs for getting the metadata of the file and in this code I am converting them to file object because the uploadfile function accepts file objects.

Would be great if I could get any help on this issue.

Thanks in advance.

What errors do you get?

What metadata are you trying to get from the file that is pushing you down the blob route? From what I can read from the code, is it only the filename and size? I think both of those are part of the File API .


I’m not knowledgable about this topic particularly, but I was interested understanding. I was Googling and found some StackExchange questions about a similar problem, but I would expect a lot more upvotes given that it’s a popular platform and a popular action – so take this with a grain of salt.

Interesting post: canvas - Error loading Blob to img in Safari (WebKitBlobResource error 1.) - Stack Overflow


Are you initializing .size somewhere else in your code?

   // Calculate total bytes for all files
      instance.data.size.forEach((fileSize) => {
          totalBytes += fileSize;
      });

FYI: if you’re trying to notify the Bubble developer, you can use context.reportDebugger instead of console.warn / error.


TIL Apple’s documentation is poor at best: Blob | Apple Developer Documentation

The interesting part is that i am not getting any error on safari but on chrome that i am using on the iOS it crashes when i upload a file.

I am using the following metadata

  • filename
  • size
  • extension

I am also not that knowledgeable that why i might be making some silly mistake. regarding the .size it is a state of the element which stores the sizes of all the files that are selected.

I have dropped the blob approach and getting the required information directly from the file object and it seems to be working fine.

I guess the issue was the conversion from file object to blob was expensive.

1 Like