Sharp: Wrong output type after .resize

Created on 4 Dec 2018  路  7Comments  路  Source: lovell/sharp

I am calling sharp(tmpFilePath).resize(150, 150).toFile(resizedFilePath) but the output file that's being produced is showing as type application/octet-stream rather than an image/jpeg, which is the original file type. I am using Angular and downloading/uploading to Firebase storage via cloud functions. When I download the source file and upload it right back to Firebase without calling the sharp API first, the newly uploaded file is an image/jpeg file, so I am pretty sure it's something I am doing incorrectly with the Sharp api. Thanks in advance for any assistance.

Original file:
image

File returned by Sharp API:
image

My function from index.ts:

export const resizeImages = functions.storage.object().onFinalize(async object => { 
    try {
        console.log(object);
        const bucket = admin.storage().bucket(object.bucket);
        const filePath = object.name;
        const fileName:string = filePath.split('/').pop();
        const bucketDir = dirname(filePath);
        console.log("filePath: " + filePath + "; fileName: " + fileName + "; bucketDir: " + bucketDir);

        if (bucketDir === 'profile-image' && object.contentType.includes('image')){
            console.log("A profile picture was added...")
            //The file is a profile picture...
            if (fileName.includes('unsized@')) {
                console.log("The picture that was added hasn't been sized yet...")
                //The file needs to be resized...
                    const workingDir = join(tmpdir(), 'thumbs');
                    const tmpFilePath = join(workingDir, fileName);

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

                    // 2. Download Source File
                    await bucket.file(filePath).download({
                    destination: tmpFilePath
                    });
                    console.log("Downloaded the source file");
                    console.log(tmpFilePath);

                    // 3. Resize the image  ********THIS PART IS NOT HAPPENING CORRECTLY
                    console.log("About to start resizing...");
                    const resizedfileName: string = fileName.split('@').pop();
                    const resizedFilePath = join(workingDir, resizedfileName);
                    await sharp(tmpFilePath).resize(150, 150).toFile(resizedFilePath);
                    console.log("The image resizing is complete: "+ resizedFilePath);

                    // 4. Upload the resized image
                    const resizedImageUploadSnapshot = await bucket.upload(resizedFilePath, {destination: join('profile-image', resizedfileName)});
                    console.log("Uploaded the resized image ");

                    // 5. Cleanup remove the tmp/thumbs from the filesystem
                    await fs.remove(workingDir);
                    console.log("FUNCTION COMPLETED SUCCESSFULLY!")
                    return true;
            } else {
                return false;
            }
        } else {     
            console.log('exiting function');
            return false;
        }

    } catch (error) {
        console.log(error);
        return error;
    }

Most helpful comment

@avilao Re: "image data was from the previous upload" - if you're recycling the same filename for different images then you'll need to disable libvips cache.

All 7 comments

Hello, sorry, this question relates to things well beyond the realms of sharp so perhaps a site like StackOverflow might be a better place to ask this.

I am calling sharp(tmpFilePath).resize(150, 150).toFile(resizedFilePath) but the output file that's being produced is showing as type application/octet-stream rather than an image/jpeg, which is the original file type. I am using Angular and downloading/uploading to Firebase storage via cloud functions. When I download the source file and upload it right back to Firebase without calling the sharp API first, the newly uploaded file is an image/jpeg file, so I am pretty sure it's something I am doing incorrectly with the Sharp api. Thanks in advance for any assistance.

Original file:
image

File returned by Sharp API:
image

My function from index.ts:

export const resizeImages = functions.storage.object().onFinalize(async object => { 
    try {
        console.log(object);
        const bucket = admin.storage().bucket(object.bucket);
        const filePath = object.name;
        const fileName:string = filePath.split('/').pop();
        const bucketDir = dirname(filePath);
        console.log("filePath: " + filePath + "; fileName: " + fileName + "; bucketDir: " + bucketDir);

        if (bucketDir === 'profile-image' && object.contentType.includes('image')){
            console.log("A profile picture was added...")
            //The file is a profile picture...
            if (fileName.includes('unsized@')) {
                console.log("The picture that was added hasn't been sized yet...")
                //The file needs to be resized...
                    const workingDir = join(tmpdir(), 'thumbs');
                    const tmpFilePath = join(workingDir, fileName);

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

                    // 2. Download Source File
                    await bucket.file(filePath).download({
                    destination: tmpFilePath
                    });
                    console.log("Downloaded the source file");
                    console.log(tmpFilePath);

                    // 3. Resize the image  ********THIS PART IS NOT HAPPENING CORRECTLY
                    console.log("About to start resizing...");
                    const resizedfileName: string = fileName.split('@').pop();
                    const resizedFilePath = join(workingDir, resizedfileName);
                    await sharp(tmpFilePath).resize(150, 150).toFile(resizedFilePath);
                    console.log("The image resizing is complete: "+ resizedFilePath);

                    // 4. Upload the resized image
                    const resizedImageUploadSnapshot = await bucket.upload(resizedFilePath, {destination: join('profile-image', resizedfileName)});
                    console.log("Uploaded the resized image ");

                    // 5. Cleanup remove the tmp/thumbs from the filesystem
                    await fs.remove(workingDir);
                    console.log("FUNCTION COMPLETED SUCCESSFULLY!")
                    return true;
            } else {
                return false;
            }
        } else {     
            console.log('exiting function');
            return false;
        }

    } catch (error) {
        console.log(error);
        return error;
    }

Have the same problem. More or lesse the same code Did you manage to solve it?

Hi, yes I did solve it but I don't remember exactly how at the moment. I can pull it up sometime this weekend and I'll post the new code. It wasn't an issue with the sharp api. It may have been that I needed to specify a file extension in all the file names?? I'll confirm back once I can look at the code.

Thank you so much :)

@avilao Sorry I couldn't get to this over the weekend! I've made a few other changes since this post, but I believe the one that resolved this issue was changing the following lines:

const tmpFilePath = join(workingDir, fileName + '.jpeg');
const resizedFilePathTemp = join(workingDir, resizedfileName + '.jpeg');

Let me know if that doesn't work! Good luck!

Something like that solved the issue. But I actually had to stop using sharp because of another issue (image data was from the previous upload, in Firebase functions) and am now using ImageMagick.

Thanks for the help :)

@avilao Re: "image data was from the previous upload" - if you're recycling the same filename for different images then you'll need to disable libvips cache.

Was this page helpful?
0 / 5 - 0 ratings