Search code examples
node.jsbase64blobbufferarraybuffer

Get the Blob Using Node Multer Buffer And Convert Blob To Base 64


I'm trying to get the Uint8Contents as Blob to convert to base64 and store it as PgSQL bytea coming from the ArrayBuffer/Buffer using multer middleware for Expressjs.

Most of the answers refer to saving it in a file system first, but how would you use the multer memory storage? (I've used it this way)

import { Router, Request, Response } from 'express'
import multer from 'multer'

const storage = multer.memoryStorage()
const upload = multer({ storage: storage })
const api = Router()

api.post('/customer/:customer_id/photo', upload.single('photo'),
    async (req: Request, res: Response) => {

    const customerId = req.params.customer_id
    const photoBuffer = req?.file?.buffer as Buffer

    const arrayBuffer = photoBuffer.buffer.slice(
      photoBuffer.byteOffset,
      photoBuffer.byteOffset + photoBuffer.byteLength
    )

    const uInt8Contents = photoBuffer.readUInt8(photoBuffer.byteOffset)
    console.log("uInt8Contents",uInt8Contents)

    // const arrayBuffer = Uint8Array.from(photoBuffer).buffer
    // const photoBlob = Buffer.from(arrayBuffer).Blob([arrayBuffer])
    console.log("bufferPhoto", arrayBuffer)

    // TODO: Need a code for converting array buffer or buffer to be the correct image Blob

    const base64Photo = Buffer.from(arrayBuffer).toString('base64')
    // Store base 64 photo in PgSQL bytea
    // ...
  }
)

I just couldn't figure out how to get the correct Blob to be converted as base64 and store it in PgSQL as bytea.

So, the question is: On the second to the last line, how would I convert the file into a Blob?

I get this output, but it does not seem to be the Uint8Contentsof the blob because the image does not display at all.

ArrayBuffer {
  [Uint8Contents]: <ff d8 ff e0 00 10 4a 46 49 46 00 01 01 01 00 48 00 48 00 00 ff e2 02 a0 49 43 43 5f 50 52 4f 46 49 4c 45 00 01 01 00 00 02 90 6c 63 6d 73 04 30 00 00 6d 6e 74 72 52 47 42 20 58 59 5a 20 07 dd 00 0a 00 08 00 17 00 2b 00 36 61 63 73 70 41 50 50 4c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... 2527 more bytes>,
  byteLength: 2627
}

Solution

  • I found this issue: https://github.com/dherault/serverless-offline/issues/464

    It was basically a serverless-offline issue: When a server is running in serverless-offline and the image is uploaded, the binary image gets distorted like this:

    Distorted binary image

    Where the binary image should look like this, instead: enter image description here

    In short, the characters are being changed by serverless-offline. The link, however, suggests that if you are going to deploy the code in a non-serverless-offline environment, it will work.

    So, this code will still work when deployed:

    import { Router, Request, Response } from 'express'
    import multer from 'multer'
    
    const storage = multer.memoryStorage()
    const uploadPhoto = multer({ storage: storage }).single('upload')
    const api = Router()
    
    v1Api.post('/user/:user_id/photo', uploadPhoto, async (req: Request, res: Response) => {
      const userId = req.params.user_id
      const photoBuffer = req?.file?.buffer as Buffer
      const binaryPhoto = Buffer.from(photoBuffer).toString('binary')
      const base64Photo = Buffer.from(binaryPhoto).toString('base64')
      console.log(base64photo) // Save this base64photo as bytea
    })
    

    Otherwise, configure the serverless.yml to support binary using this plugin aws-serverless-express-binary.

    Edit

    We deployed it in an environment and it seems to work correctly.