Home > Software design >  Displaying binary data in a HBS view from MongoDB - Node js
Displaying binary data in a HBS view from MongoDB - Node js

Time:07-27

I have a hbs view which is receiving and displaying some data that I am pulling from MongoDB. It is displaying all my data correctly except for the binary data which I am using inside of an img element. If I copy the binary data from the MongoDB document and put it in the img element it displays in the browser. For this reason I feel that the variable I am referencing is incorrect?

I have also tried to use 'img.$binary' and that does not show any data at all. This would seem to me the way to do it though with 'img' being an object?

But when I log 'img' to the console it seems to be the right one. When I log 'img.$binary' it is undefined. I am definitely getting some data in the img tag as it shows this when I run node js (with 'img' in the appropriate place in hbs view):

Screenshot of what displays in the browser

HTML:

HTML of what data is showing

My route:

router.get('/', async (req, res) => {
    const products = await Product.find()
    res.render('shop', {
      title: 'Shop',
      products: products
    })
})

Mongoose Model:

const ProductSchema = new mongoose.Schema(
    {
        title: { type: String, required: true, unique: true },
        desc: { type: String, required: true },
        img: { type: Buffer },
        categories: { type: Array },
        size: { type: String },
        colour: { type: String },
        price: { type: Number, required: true },
    },
    { timestamps: true }
)

MongoDB Collection:

{
    "_id" : ObjectId("62dd1127884e20dcfbb09a6c"),
    "title" : "'Northface tshirt'",
    "desc" : "'test'",
    "img" : { "$binary" : "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6CAIAAAAH...(shortened for viewability), "$type" : "00" },
    "categories" : [],
    "size" : "'XL'",
    "colour" : "'White'",
    "price" : 80,
    "createdAt" : ISODate("2022-07-24T09:30:15.974Z"),
    "updatedAt" : ISODate("2022-07-24T09:30:15.974Z"),
    "__v" : 0
}

HBS view:

<body>
            <div >
            {{!-- Object --}}
            {{#each products}}
                <div >
                    <img src="data:image/jpg;base64,{{img}}">
                    {{!-- String --}}
                    <h2>{{title}}</h2>
                        {{!-- Array --}}
                        {{#each categories}}
                            {{!-- Strings --}}
                            <p>Apparel Type: {{apparelType}}</p>
                            <p>Gender: {{gender}}</p>
                        {{/each}}
                            <p>Size: {{size}}</p>
                            <p>Price: {{price}}</p>
                            <p>Colour: {{colour}}</p>
                </div>
            {{/each}}
            </div>

Any help would be greatly appreciated, I have searched for a couple hours now and seen some similar issues but nothing has helped so far. Hoping someone with more experience with data will know what is going wrong here. Thanks in advance.

CodePudding user response:

Not exactly an answer for inserting the binary data straight into the img tag but I have now found a way to display the DB document images dynamically.

Firstly, I added a route to view the img for each document in the collection by it's id:

//VIEW PRODUCT IMG
router.get('/:id/img', async (req, res) => {
  try {
    const product = await Product.findById(req.params.id)
    if (!product || !product.img) {
      throw new Error()
    }
    res.set('Content-Type', 'image/jpg')
    res.send(product.img)
  } catch (e) {
    res.status(404).send() 
  }
})

Then, modified my img src attribute to point towards the route inserted the id's of the documents dynamically in the hbs template:

<div >
  {{!-- Object --}}
  {{#each products}}
    <div >
      <img src="products/{{id}}</img">
      {{!-- String --}}
      <h2>{{title}}</h2>
      {{!-- Array --}}
      {{#each categories}}
        {{!-- Strings --}}
        <p>Apparel Type: {{apparelType}}</p>
        <p>Gender: {{gender}}</p>
      {{/each}}
      <p>Size: {{size}}</p>
      <p>Price: {{price}}</p>
      <p>Colour: {{colour}}</p>
    </div>
  {{/each}}
</div>

I can now display the images as intended:

HTML page image

  • Related