Functions-samples: Generate thumbnail is generating application/octet-stream as type

Created on 15 Nov 2017  路  5Comments  路  Source: firebase/functions-samples

I'm following the exact example to generate a thumbnail from a image, but the image is getting the application/octet-stream type on the GCS instead of image/jpeg.
I don't know what i need to change in this code so the image will have the properly extension.

static generateThumbnail(filePath) {
    return new Promise((resolve, reject) => {
      // File and directory paths.
      const fileDir = path.dirname(filePath);
      const fileName = path.basename(filePath);
      const thumbFilePath = path.normalize(path.join(fileDir, `${THUMB_PREFIX}${fileName}`));
      const tempLocalFile = path.join(os.tmpdir(), filePath);
      const tempLocalDir = path.dirname(tempLocalFile);
      const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath);

      // Exit if the image is already a thumbnail.
      if (fileName.startsWith(THUMB_PREFIX)) {
        console.log('Already a Thumbnail.');
        return;
      }

      // Cloud Storage files.
      const bucket = gcs.bucket(BUCKET);
      const file = bucket.file(filePath);
      const thumbFile = bucket.file(thumbFilePath);

      // Create the temp directory where the storage file will be downloaded.
      return mkdirp(tempLocalDir).then(() => {
        // Download file from bucket.
        return file.download({ destination: tempLocalFile });
      }).then(() => {
        console.log('The file has been downloaded to', tempLocalFile);
        // Generate a thumbnail using ImageMagick.
        return spawn('convert', [tempLocalFile, '-thumbnail', `${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>`, tempLocalThumbFile]);
      }).then(() => {
        console.log('Thumbnail created at', tempLocalThumbFile);
        // Uploading the Thumbnail.
        return bucket.upload(tempLocalThumbFile, { destination: thumbFilePath });
      }).then(() => {
        console.log('Thumbnail uploaded to Storage at', thumbFilePath);
        // Once the image has been uploaded delete the local files to free up disk space.
        fs.unlinkSync(tempLocalFile);
        fs.unlinkSync(tempLocalThumbFile);
        // Get the Signed URLs for the thumbnail and original image.
        const config = {
          action: 'read',
          expires: '03-01-2500'
        };
        return Promise.all([
          thumbFile.getSignedUrl(config),
          file.getSignedUrl(config)
        ]);
      }).then((results) => {
        console.log('Got Signed URLs.');
        const thumbResult = results[0];
        const originalResult = results[1];
        const thumbFileUrl = thumbResult[0];
        const fileUrl = originalResult[0];
        // Add the URLs to the Database
        resolve({ path: fileUrl, thumbnail: thumbFileUrl });
      });
    });
  }

Most helpful comment

When uploading the file to Cloud Storage here: return bucket.upload(tempLocalThumbFile, { destination: thumbFilePath });
You need to pass some metadata that indicates the mime type of the file. For instance the same as the original image:

return bucket.upload(tempLocalThumbFile, {
    destination: thumbFilePath,
    metadata: {
        contentType: event.data.contentType // That's the event object from the Cloud Functions trigger
    }
});

All 5 comments

I was looking into an "application/octet-stream" issue and eventually stumbled upon your report. You should probably enable syntax highlighting and simplify your code, there are lots of unrelated things in there. So I'm not sure if it could help but I found this page to help me understand why I get "application/octet-stream" when uploading an image: add file metadata.

Thanks man, that would most likely fix the application/octet-stream problem.
But i'm generating the thumbnail now with sharp.

When uploading the file to Cloud Storage here: return bucket.upload(tempLocalThumbFile, { destination: thumbFilePath });
You need to pass some metadata that indicates the mime type of the file. For instance the same as the original image:

return bucket.upload(tempLocalThumbFile, {
    destination: thumbFilePath,
    metadata: {
        contentType: event.data.contentType // That's the event object from the Cloud Functions trigger
    }
});

And yes, it looks like the Sharp sample already sets the Content Type. I'll try updating the ImageMagick samples.

Add this line
return bucket.upload(thumbPath, {
destination: join(bucketDir, thumbName),
metadata: {
contentType: 'image/jpeg' // That's the event object from the Cloud Functions trigger
}
})

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rodrigosol picture rodrigosol  路  3Comments

IchordeDionysos picture IchordeDionysos  路  3Comments

abhilash1in picture abhilash1in  路  4Comments

nhathiwala picture nhathiwala  路  4Comments

aaronte picture aaronte  路  6Comments