George
George

Reputation: 365

Firebase Storage | File is "application/octet-stream" on upload from node.js cloud function

Problem

I have a callable cloud function which generates thumbnails using Sharp, then uploads them to Firebase Storage

const { getStorage } = require('firebase-admin/storage');
const bucket = getStorage().bucket();

const filePath = ref;
    const workingDir = join(tmpdir(), 'thumbs');
    const downloadedFilePath = join(workingDir, 'source');
    const destinationDir = getThumbDir(dirname(filePath));

    // 1. Ensure thumbnail dir exists
    await ensureDir(workingDir);

    // 2. Download Source File
    await bucket.file(filePath).download({
        destination: downloadedFilePath,
    });

    const sizes = [100, 200, 300]

    const uploadPromises = sizes.map(async size => {
        const thumbName = `@${size}.jpg`;
        const thumbPath = join(workingDir, thumbName);
        const destinationPath = `${destinationDir}/${thumbName}`

        // Resize source image
        await sharp(downloadedFilePath)
            .resize(size, size)
            .toFile(thumbPath);
        
        
        // Upload to GCS
        return await bucket.upload(thumbPath, {
            destination: destinationPath,
            contentType: "image/jpeg",
            
        });
    });

    // 4. Run the upload operations
    await Promise.all(uploadPromises);
    await remove(workingDir);

The problem is that the files all appear as type "application/octet-stream" in my database. Why is this? Note that I am using a complete local firebase emulator for all of this, could that have an affect?

Details

using node.js
firebase tools 11.16.0
firebase-admin": "^11.2.1
sharp: ^0.31.1

Upvotes: 1

Views: 1108

Answers (1)

Caerbannog
Caerbannog

Reputation: 825

The second argument for bucket.upload() is named options and does not have a property contentType. It is probably just ignored. Documentation : https://googleapis.dev/nodejs/storage/latest/global.html#UploadOptions

You are actually interested in options.metadata.contentType. So you should fix your code like this:

        // Upload to GCS
        return await bucket.upload(thumbPath, {
            destination: destinationPath,
            metadata: {
                contentType: "image/jpeg",
            },            
        });

The application/octet-stream type is the default, which basically means that the format is unknown. Debugging the mime types can be frustrating because some tools (gsutil and I think the GCS console) can detect the type from the filename during upload ; so reproducing the problem manually is not straightforward. Documentation: https://cloud.google.com/storage/docs/metadata#content-type

Upvotes: 2

Related Questions