Search code examples
mysqlruby-on-railsblob

Ruby on Rails display blob as image


I am creating a Ruby on Rails application where I have images stored as blobs in a MySQL database. I am querying the database and trying to display the image in my view, but I'm not able to style it or put other HTML around it, it just displays on a black background.

This is what I am doing in Controller:

def get
   @data = Data.find(1)
   send_data @data.image_object, :type => 'image/png', :disposition => 'inline'
end

This displays the image with no other HTML and I can't style it. What can I do? image_object is a blob and I need to convert that to an image I can render in my view. I cannot use GCP, AWS or Azure cloud storage, I need to store the image in MySQL.

Any help would be appreciated, thank you in advance.


Solution

  • You need to render a page (you are downloading the image instead).

    So in your controller:

    def show # better to stick with Rails conventions, use "show" rather than "get"
       @data = Data.find(1)
    end
    

    This will automatically render the app/views/controllername/show.html.erb page, using the app/views/layouts/application.html.erb layout

    <img src=#{@data.image_object} />
    

    This rendering as an image tag assumes that your image is stored not as a blob but in data-uri format: "data:image/png;base64,<base64-encoded image data>".

    If you really want to stick with blob storage, you'll have to convert it in the controller or the model.

    Now you have an image element that you can wrap in a div, and style with css.

    And finally... you are not obligated to use cloud storage to store the image as a separate jpg or png file, you can store it in a directory on your own server. Typically it's a directory outside the Rails directory structure, so that it survives code updates. This would be a perfectly normal way to upload and download image files. Rails 7 now accommodates this, but with Rails 6 and before we would use something like the Carrierwave gem. When you store images as separate files, rendering them in the view is more straightforward than trying to render a blob.