Home > Software engineering >  How to show BASE64 stored data in SQL Server in an Image in WebForms ASP.NET - RDLC report
How to show BASE64 stored data in SQL Server in an Image in WebForms ASP.NET - RDLC report

Time:11-07

I've Asset Codes which I'm converting into BASE64 like this:

private string GenerateBarcode(string BarCode)
{
    string generatebarcode = BarCode;

    GeneratedBarcode barcode = BarcodeWriter.CreateBarcode(generatebarcode, BarcodeWriterEncoding.Code128);

    barcode.ResizeTo(400, 120);
    barcode.SetMargins(10);
    barcode.ChangeBarCodeColor(Color.Black);

    Image MyBarCodeImage = barcode.Image;

    var myArray = (byte[])new ImageConverter().ConvertTo(MyBarCodeImage, typeof(byte[]));
    string temp_inBase64 = Convert.ToBase64String(myArray);

    return temp_inBase64;
}

And after this, I'm saving this BASE64 into my database.

Now, getting this into my Dataset, showing in tabular form.

At the RDLC level, I've tried:

  • Drop an Image report control from toolbox.
  • Right click on the image and choose image properties
  • Set the image source to database
  • Set the MIME type to a suitable value, for example image/bmp.
  • Set use this field to the image value which you have,

For example =Fields!Code.Value. The parameter type should be Text.

But it's not showing anything in the RDLC Report Viewer.

I've found many solutions on the internet but none of them seems works to me. Is there something that I missed?

I use Visual Studio 2019 Community, .NET Framework 4.7.2, Microsoft.ReportViewer.WebForms 15.0.0.0

Thanks.

CodePudding user response:

If you are using webforms, you can use the asp Image control

<asp:Image ID="ImageObject" runat="server" Width="400"/>

And from server side do something like this

public void SetImageData(byte[] inArray)
    {
        string strBase64Logo = Convert.ToBase64String(inArray);
        if (!string.IsNullOrWhiteSpace(strBase64Logo))
        {
            ImageObject.Visible = true;
            ImageObject.ImageUrl = "data:Image/png;base64,"   strBase64Logo;
        }
        else
        {
            ImageObject.Visible = false;
        }
            
    }

Save (and load) your image info as byte[] and let the control know that you will use an image from Base64 as data:Image/png;base64.

Just a heads-up: if you are storing your images as base64 in database, it will grow a lot really fast, and there will be network overhead when retrieving multiple images from database and when sending them to the page. I had a project with exactly this scenario and we found out that it was slow to load multiple images at the same time, as the queries returned a lot of data just from the images.

CodePudding user response:

Ok, the technology for the report viewer was around for a VERY long time.

Hence, store the image as raw binary file bytes, and NOT base64.

Besides, storing the image as raw binary bytes from the picture file will save quite a bit of space in the database anyway.

Then, if you for some reason need to pull that picture and display in a webform, THEN you convert to base64 string.

So, in the report designer, you have this correct, but you're storing the image as a base64 string, and RDL reports don't use or know about base64 strings.

So, in web land? Sure, we live and die by that format, but the reporting system goes all the way back to windows land. So, you have to feed the report viewer a raw binary image.

About the only monkey wrench here would be if changing that format is too much of a pain for you. I would if possible, run a process on the existing data, and covert the base64 strings back to a binary array, and save that back into the database. So, use a varbinary(max) column in place of a string column.

As noted, for rending non reports in a web page? Well, then convert the binary to a base64 string.

this DOES mean of course you can't say bind a eval() expression to a gridview/list view etc.

However, with ease you can you can with rather ease convert the binary data into a base64 string on the fly with ease.

But, doing the reverse will certainly be greater pain (for a report).

So, say I have this gridView, and I need to display that binary picture:

<asp:GridView ID="GridView1" 
    runat="server" AutoGenerateColumns="False" DataKeyNames="ID"
    CssClass="table" Width="50%" OnRowDataBound="GridView1_RowDataBound"
    >
    <Columns>
        <asp:BoundField DataField="Fighter" HeaderText="Fighter"        />
        <asp:BoundField DataField="Engine"  HeaderText="Engine"         />
        <asp:BoundField DataField="Thrust"  HeaderText="Thrust (lbs)"   />
        <asp:BoundField DataField="FirstFlight" HeaderText="First Flight"
            DataFormatString ="{0:MM dd yyyy}"  ItemStyle-Width="100"    />
        <asp:BoundField DataField="Description" HeaderText="Description"    />
        <asp:TemplateField ControlStyle-Width="132">
            <ItemTemplate>
                <asp:Image ID="Image1" runat="server"/>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

And my code to load - along with the "binary" convert in the row data bound event.

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadGrid();
    }

    void LoadGrid()
    {
        string strSQL =
            @"SELECT ID, Fighter,Engine, Thrust, FirstFlight, Description, MyImage
            FROM Fighters ORDER BY Thrust";

        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                conn.Open();
                DataTable rstData = new DataTable();
                rstData.Load(cmdSQL.ExecuteReader());
                GridView1.DataSource = rstData;
                GridView1.DataBind();
            }
        }
    }

    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            DataRowView gData = e.Row.DataItem as DataRowView;
            Image MyImage = e.Row.FindControl("Image1") as Image;

            MyImage.ImageUrl =
                @"data:image/jpeg;base64,"   Convert.ToBase64String((byte[])gData["MyImage"]);
        }
    }

And now I see/get this:

enter image description here

But, if we create a report

enter image description here

Then I can indeed bind the image control directly to the image column, and the column and it works

eg:

enter image description here

and then when I run this, I get this:

enter image description here

I think it will get a bit messy if you try to convert the base64 string to a image at runtime, but I'm open to suggestions.

So, report writer wants a raw binary (bytes) data,

And web land wants a base64 string. But, it turns out it far less efforts to convert the binary to a base64 string when required/as needed.

  • Related