skip to Main Content

When I upload a .mp3 audio file or a .jpg picture to Firebase Cloud Storage I get this error:

TypeError: Cannot read properties of undefined (reading 'byteLength')

What is byteLength?

I tried uploading a .jpg with raw uploadString. The file appeared in Storage but it was only 15B when it should have been 100KB.

The documentation Upload files with Cloud Storage on Web doesn’t say anything about specifying MIME types when uploading files.

Writing to the Storage emulator executes without errors but no files appear.

Here’s the Firebase Cloud Function I’m using.

import { initializeApp } from "firebase/app";
import * as functions from "firebase-functions";
import { getStorage, ref, uploadBytes, uploadString, connectStorageEmulator } from "firebase/storage";

const firebaseConfig = {
    apiKey: "...",
    authDomain: "my-awesome-app.firebaseapp.com",
    databaseURL: "https://my-awesome-app.firebaseio.com",
    projectId: "my-awesome-app",
    storageBucket: "my-awesome-app.appspot.com",
    messagingSenderId: "...",
    appId: "..."
};

const app = initializeApp(firebaseConfig);

export const ByteMe = functions.firestore.document('ByteMe/{userID}').onUpdate((change, context) => {
    const storage = getStorage();
    const storageRef = ref(storage, 'gs://my-awesome-app.appspot.com/Pictures/bootchkas.jpg');
    connectStorageEmulator(storage, "localhost", 9199); // comment out to write to the cloud

    async function uploadPicture() {
        try {
            uploadString(storageRef, './bootchkas.jpg').then((snapshot) => {
                console.log('Uploaded a raw string!');
            });
        } catch (error) {
            console.error(error);
        }
    }
    
    return uploadPicture();
});

2

Answers


  1. Chosen as BEST ANSWER

    As @Dharmaraj and @Alexander N. said, uploadString just uploads the subsequent string, not a file. The error message

    TypeError: Cannot read properties of undefined (reading '...')
    

    means that undefined is a missing ES module that you didn't import.

    The following code almost uploads a file...with one problem.

    import file from "./bootchkas.jpg";
    
    export const ByteMe = functions.firestore.document('ByteMe/{userID}').onUpdate((change, context) => {
        const storage = getStorage();
        const storageRef = ref(storage, 'gs://my-awesome-app.appspot.com/Pictures/bootchkas.jpg'); // location to write to
        connectStorageEmulator(storage, "localhost", 9199); // comment out to write to the cloud
    
        const metadata = {
            contentType: 'image/jpeg',
        };
    
        async function uploadPicture() {
            try {
                await uploadBytes(storageRef, file, metadata);
                console.log('Uploaded a file!');
            } catch (error) {
                console.error(error);
            }
        }
    
        return uploadPicture();
    });
    

    uploadBytes uploads files (or blobs). It take three parameters: the storageRef or path to a location in Storage; file, which is the file to be uploaded to Storage; and metadata, which includes the MIME type of the file.

    I've set the MIME contentType to 'image/jpeg'.

    This leaves file. We need to import the file as an ES module:

    import file = './bootchkas.jpg`;
    

    But that doesn't work because bootchkas.jpg isn't an ES module.

    We need to use WebPack to make an ES module from bootchkas.jpg. The WebPack documentation has a section Loading Images. I followed the tutorial and was able to load bootchkas.com into a HTML page. But when I tried to use WebPack with my Firebase Cloud Function it threw error after error.

    Here's the webpack.config.js I ended up with (bizarrely, the tutorial use CommonJS modules):

    import path from "path"
    
    const __dirname = "/Users/TDK/VisualStudioCodeProjects/CloudFunctions/functions"
    
    const exportMe = {
        mode: 'development',
        entry: './src/index.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist'),
        },
        module: {
            rules: [
                {
                    test: /.(png|svg|jpg|jpeg|gif)$/i,
                    type: 'asset/resource',
                },
            ],
        },
    };
    
    export default exportMe;
    

    This throws about a half-dozen error, which I fixed one by one.

    Then I restarted the Firebase emulator and it couldn't read functions/package.json. WebPack requires changing "main": "./src/index.js", to "private": true, which makes Firebase unable to reach your Cloud Functions. Trying to get WebPack to work with Firebase Cloud Functions is too difficult.


  2. As @Dharmaraj indicated, it looks like you are just uploading the string ./bootchkas.jpg -> its exactly 15 bytes long. Is this the code you wanted to use to upload the file? If it is, it won’t find the file, but only find the string ./bookchkas.jpg.

    If you want to upload a file as a string you would either need to encode the file as base64 or load the file itself and send that to firebase storage. If using the browser APIs, you can fetch the file using something akin to this. If using nodejs and a server side application, you will want to refer to the file using the filesystem nodejs package.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search