C# Convert BLOB to jpg, resize, then back to BLOB I am trying to convert a BLOB that is stored in a database to a JPG and then I need to display it on an html form in a C# application.
A little backstory first - this is an older web app that was designed to take a JPG (photo) that was stored as a path in the database, resize it, then show as a BLOB. This functionality needs to stay in place, but now one of the systems is changing and the photo is going to be stored in the database as a BLOB instead of a path to a photo (\servername\images\xyz.jpg).
One system still needs the image to be resized then sent back as a BLOB to display. The other systems that call this web-app will need the BLOB converted to a JPG to display.
The code below works, but I think it might have put an unnecessary load on the server, because this morning the system was laggy and some features were impossible to use. I have a feeling that the .Save is the troublemaker here since I am calling it twice. I know the image doesn't need to be saved anywhere physically, as long as the web-app can call and have it display to the site. Is there anything I can change here to skip saving an image on the server and just display it so it doesn't use up a ton of resources?
protected void Page_Load(object sender, EventArgs e)
{
   byte[] byteImage = null;
    string ID = Request.QueryString[&quot;id&quot;];
    string imageFile = &quot;\\\\server\\c$\\inetpub\\wwwroot\\web-app\\images\\&quot; + ID+ &quot;.jpg&quot;;
    string server = Request.ServerVariables[&quot;server_name&quot;];
    var serverNameList = db.Servers.Select(x =&gt; x.ServerName).ToList();

    connection.Open();
    SqlCommand sqlCommand = new SqlCommand(&quot;sp&quot;, connection);
    sqlCommand.Parameters.Add(&quot;@ID&quot;, SqlDbType.VarChar);
    sqlCommand.Parameters[&quot;@ID&quot;].Value = ID;
    sqlCommand.CommandType = CommandType.StoredProcedure;
    SqlDataReader dr = sqlCommand.ExecuteReader();                               

    while (dr.Read())
    {
        byteImage = (byte[])dr[&quot;BLOB&quot;];
    }

    if (byteImage != null)
    {
        using (MemoryStream ms = new MemoryStream(byteImage))
        {
            //saving to jpg image
            Image img = new Bitmap(ms);
            img.Save(imageFile, ImageFormat.Jpeg);

            Response.Clear();
            Response.CacheControl = &quot;public&quot;;
            Response.Cache.SetExpires(DateTime.Now.AddDays(1.0));
            Response.ContentType = &quot;Image/jpeg&quot;;
               
            if (serverNameList.Contains(server)) // if user is coming from a specific server, resize the image then send back
            {
                byte[] resizedImage = GetResizedImage(imageFile, 300, 400);
                Response.OutputStream.Write(resizedImage, 0, resizedImage.Length);
            }
            else // skip resize and show image as jpg
            {
                Response.BinaryWrite(byteImage);
            }
        }
    }
    else // image is null
    {
        imageFile = HttpRuntime.AppDomainAppPath + &quot;PERSON.GIF&quot;;
    }         
}
    
private byte[] GetResizedImage(string path, int width, int height)
{
    Bitmap bitmap1 = new Bitmap(path);
    double height1 = bitmap1.Height;
    double width1 = bitmap1.Width;
    double num = 1.0;
    if (width &gt; 0)
        num = width / width1;
    else if (height &gt; 0)
    num = height / height1;
    MemoryStream memoryStream = new MemoryStream();
    Bitmap bitmap2 = new Bitmap((int)(width1 * num), (int)(height1 * num));
    bitmap2.SetResolution(150f, 150f);
    Graphics graphics = Graphics.FromImage(bitmap2);
    graphics.CompositingQuality = CompositingQuality.HighQuality;
    graphics.Clear(Color.White);
    graphics.DrawImage(bitmap1, new Rectangle(0, 0, (int)(num * width1), (int)(num * height1)), new Rectangle(0, 0, (int)width1, (int)height1), GraphicsUnit.Pixel);
    bitmap2.Save(memoryStream, ImageFormat.Jpeg);
    return memoryStream.ToArray();
}
Welcome to CodeReview! I hope you get some good feedback.
Absolute paths
string ID = Request.QueryString[&quot;id&quot;];
string imageFile = &quot;\\\\server\\c$\\inetpub\\wwwroot\\web-app\\images\\&quot; + ID+ &quot;.jpg&quot;;

This has a few issues. First, it's typical for a server to be in a &quot;jail&quot; where it shouldn't have access to the filesystem at large, and should only access data from its own local directory. This is for security purposes. Though I haven't done this in a long time, it seems the ASP.NET way of safely accessing such paths is MapPath.
Second: it's crucially important that you do some validation on ID. In its current state a hacker could easily construct a path navigation exploit where the ID contains ..\..\.. (etc) to explore the rest of the filesystem if the server is misconfigured.
Managing your connection
If connection is an SqlConnection, it implements IDisposable, and as such you should put it in a using. The same is true of SqlCommand.
Add-with-value
You should prefer AddWithValue over a separated Add/.Value assignment here;
sqlCommand.Parameters.Add(&quot;@ID&quot;, SqlDbType.VarChar);
sqlCommand.Parameters[&quot;@ID&quot;].Value = ID;

Read-in-loop
This:
while (dr.Read())
{
    byteImage = (byte[])dr[&quot;BLOB&quot;];
}

should probably not use a loop. Since it seems you expect only one row returned,

Read() once;
assert that it returned true;
assign byteImage;
Read() again;
assert that it returned false.

Streamed image creation
GetResizedImage creates a memory stream. It should not. Response already has an OutputStream, and you should be writing to that directly. The one thing to double-check with this approach is that Content-Length is still set correctly, which is probably only possible if BufferOutput is enabled.
Avoiding files
As to your original question, which I never really addressed:

Is there anything I can change here to skip saving an image on the server and just display it so it doesn't use up a ton of resources?

Yes! As long as you get an image from the database, you always Save() it to the disc. However, this file is only used if the server name is approved. Move your save within the name check, and fewer cases will require disc I/O.
Even further: if this is the only code that touches that file, that file should not exist at all and you should not be doing a round trip to the disc. Once you have your img, pass that to GetResizedImage instead of a path string.
Bug?
There is a mechanism here:
imageFile = HttpRuntime.AppDomainAppPath + &quot;PERSON.GIF&quot;;

which looks like it's supposed to substitute a default image if none is returned from the database. However, that file is never used. This logic needs to be rearranged so that it is. If you get back a null from the database, load this file into your byteImage.