0

I am trying to retrieve jpeg files stored in SQL Server and present these in html using img src="filepath" but my C# code is returning the actual image, not a URL path to the image and this just displays a tiny image box with an x in it.
How can I display the image directly as an image variable. Here is the HTML page with Razor C#:

@{ 
int iFileID = 8;
string sPhotoDesc = "";
Image iPhotoImage = null;
}
<form>

<fieldset>
    <legend>FileInput</legend>
    <input type="file" id="fileinput" />
    <input type='button' id='btnLoad' value='Load' onclick="@{iPhotoImage = 
         PhotoLibraryApp.PhotoData.SelectPhoto(iFileID, out sPhotoDesc); }">
    <div id="editor"></div>
</fieldset>

<img src="@iPhotoImage" width="500" height="377">

Here is the relevant C# code in a separate file called PhotoData.cs:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Drawing;
using System.IO;
using System.Transactions;


namespace PhotoLibraryApp
{
    public class PhotoData
    {
        private const string ConnStr =
          "Data Source=.;Integrated Security=True;Initial                                   
                               Catalog=PhotoLibrary;";

     public static Image SelectPhoto(int photoId, out string desc)
      {
        const string SelectTSql = @"
        SELECT
        Description,
        Photo.PathName(),
        GET_FILESTREAM_TRANSACTION_CONTEXT()
      FROM PhotoAlbum
      WHERE PhotoId = @PhotoId";

        Image photo;
        string serverPath;
        byte[] serverTxn;

        using (TransactionScope ts = new TransactionScope())
        {
            using (SqlConnection conn = new SqlConnection(ConnStr))
            {
                conn.Open();

                using (SqlCommand cmd = new SqlCommand(SelectTSql, conn))
                {
                    cmd.Parameters.Add("@PhotoId", SqlDbType.Int).Value = photoId;

                    using (SqlDataReader rdr = cmd.ExecuteReader())
                    {
                        rdr.Read();
                        desc = rdr.GetSqlString(0).Value;
                        serverPath = rdr.GetSqlString(1).Value;
                        serverTxn = rdr.GetSqlBinary(2).Value;
                        rdr.Close();
                    }
                }
                photo = LoadPhotoImage(serverPath, serverTxn);
            }

            ts.Complete();
        }

        return photo;
    }

    private static Image LoadPhotoImage(string filePath, byte[] txnToken)
    {
        Image photo;

        using (SqlFileStream sfs =
          new SqlFileStream(filePath, txnToken, FileAccess.Read))
        {
            photo = Image.FromStream(sfs);
            sfs.Close();
        }

        return photo;
      }

  }
}
StevenJe
  • 82
  • 2
  • 14
  • Not sure if this is a direct answer to your question, but see if this helps: https://stackoverflow.com/questions/13572424/use-a-system-drawing-image-in-an-html-tag – Xedni Apr 25 '18 at 21:47

2 Answers2

0

After trying to find an answer for 3 days, the following worked. Summary, once the iPhotoImage is returned from the database SQLFilestream code, this was then converted to a byte array using TurnImageToByteArray and then the imgBytes bytes were converted to string imgString which displayed the image in HTML. Here are the additional pieces of code:

@{
//Get the file ID you want to display
int iFileID = 8;
string sPhotoDesc = "";
Image iPhotoImage = null;

iPhotoImage = PhotoLibraryApp.PhotoData.SelectPhoto(iFileID, out 
sPhotoDesc);

byte[] imgBytes = 
PhotoLibraryApp.PhotoData.TurnImageToByteArray(iPhotoImage);
string imgString = Convert.ToBase64String(imgBytes);

}

I added the following method to my PhotoData class:

  public static byte[] TurnImageToByteArray(Image img)
    {
        MemoryStream ms = new MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        return ms.ToArray();
    }

The following is the html to display the image:

 <img id="JpegImage" alt="Photo Alternative" src="data:image/jpeg;base64, @imgString">
StevenJe
  • 82
  • 2
  • 14
  • I found this entry here: @{ var base64 = Convert.ToBase64String(Model.ByteArray); var imgSrc = String.Format("data:image/gif;base64,{0}", base64); } – StevenJe May 24 '18 at 20:02
0

After more effort, I found that I could not save to Memory stream for JPEG images. This gave the ubiquitous General GDI error. The JPEG files had to be converted to bitmp images first using the following code before I could get them to display:

(var ms = new MemoryStream())
{
    Bitmap bmp = new Bitmap(imageToConvert);
    bmp.Save(ms, format);
    return ms.ToArray();
}

Another note: The JPEG files come back from SQL Filestream as an image type of Bitmap, this was what clued me in to try this along with the entry by @Amir Atasin here: A generic error occurred in GDI+, JPEG Image to MemoryStream

StevenJe
  • 82
  • 2
  • 14