ASP.NET: image quality decrease when using ashx to preview - c#

My webpage allow user upload images, and save images to SQL Server, and display images back to the user. The following code is how I save images:
FileUpload img = (FileUpload)fileUploadLocationPic;
Byte[] imgByte = null;
string strFileExtension = Path.GetExtension(img.PostedFile.FileName.ToString());
// Create a FILE
HttpPostedFile File = fileUploadLocationPic.PostedFile;
// Create byte array
imgByte = new Byte[File.ContentLength];
// force control to load data
File.InputStream.Read(imgByte, 0, File.ContentLength);
strQuery = "INSERT INTO [Table](Image) VALUES(#LocImage)";
SqlParameter ParamLocImage = new SqlParameter();
ParamLocImage.ParameterName = "#LocImage";
ParamLocImage.Value = imgByte;
cmd.Parameters.Add(ParamLocImage);
Here is how I retrieve from database using ashx:
public Stream ShowEmpImage(string PLID){
string connectionString = WebConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString;
//string conn = ConfigurationManager.ConnectionStrings["EmployeeConnString"].ConnectionString;
SqlConnection connection = new SqlConnection(connectionString);
string sql = "SELECT [Image] FROM [Table] WHERE [ID] = #PLID";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#PLID", PLID);
connection.Open();
object img = cmd.ExecuteScalar();
try
{
return new MemoryStream((byte[])img);
}
catch
{
return null;
}
finally
{
connection.Close();
}
}
public void ProcessRequest(HttpContext context){
string PLID = "";
PLID = (context.Request.QueryString["PLID"]);
context.Response.ContentType = "image/jpg";
Stream strm;
strm = ShowEmpImage(PLID);
int count = 2048;
byte[] buffer = new byte[count];
int byteSeq = 0;
try
{
byteSeq = strm.Read(buffer, 0, count);
}
catch
{
}
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, count);
}
}
At last, I use
<asp:Image ID="imageChargingLocation" runat="server" />
imageChargingLocation.ImageUrl = "~/Editor/ShowImage.ashx?PLID=" + strPLID;
to retrieve image.
But I got image quality decrease here.
What should I do? (images are jpg. Same problem when tried png.)

Related

File Corrupted when reading a BLOB object from an SQL Database

All, can someone assist.
I have problems while reading a BLOB object in SQL DB. The file download but cannot open due to file being corrupted. Error appears with any document type (pdf, docx, jpg, etc).
The code executes a Stored Procedure which fetches the binary based on two different parameters.
Here is the code:
protected void Page_Load(object sender, EventArgs e)
{
// Request.QueryString["docid"].ToString();
//string DocumentID = Request.QueryString["DocumentID"].ToString();
string DocumentID = "9163736c-8064-11e8-ab16-2c44fd826130";
string SessionId = "91494483-8064-11e8-ab16-2c44fd826130";
//Connection and Parameters
SqlParameter param1 = null;
SqlParameter param2 = null;
SqlConnection conn = new SqlConnection(
ConfigurationManager.ConnectionStrings["ProcessManagerConnectionString"].ToString());
SqlCommand cmd = new SqlCommand("sp_getdoc", conn);
cmd.CommandType = CommandType.StoredProcedure;
param1 = new SqlParameter("#DocumentID", SqlDbType.NVarChar, 100);
param2 = new SqlParameter("#SessionId", SqlDbType.NVarChar, 100);
param1.Direction = ParameterDirection.Input;
param2.Direction = ParameterDirection.Input;
param1.Value = DocumentID;
param2.Value = SessionId;
cmd.Parameters.Add(param1);
cmd.Parameters.Add(param2);
//Open connection and fetch the data with reader
conn.Open();
SqlDataReader reader =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (reader.HasRows)
{
reader.Read();
//
string doctype = reader["Extension"].ToString();
string docname = reader["Docname"].ToString();
//
Response.Buffer = false;
Response.ClearHeaders();
Response.ContentType = doctype;
Response.AddHeader("Content-Disposition",
"attachment; filename=" + docname);
//
//Code for streaming the object while writing
const int ChunkSize = 1024;
byte[] buffer = new byte[ChunkSize];
byte[] binary = (reader["Data"]) as byte[];
MemoryStream ms = new MemoryStream(binary);
int SizeToWrite = ChunkSize;
for (int i = 0; i < binary.GetUpperBound(0) - 1; i = i + ChunkSize)
{
if (!Response.IsClientConnected) return;
if (i + ChunkSize >= binary.Length)
SizeToWrite = binary.Length - i;
byte[] chunk = new byte[SizeToWrite];
ms.Read(chunk, 0, SizeToWrite);
Response.BinaryWrite(chunk);
Response.Flush();
}
Response.Close();
}
No need to do any chunking here. You already have the binary data loaded into memory. Just make a single call to:
Response.BinaryWrite(binary);
Avoid creating MemoryStream and whatnot. I have a feeling there is a bug with your chunking code.
If you are looking to reduce the memory usage in your app when streaming binary data, you should look into using CommandBehavior.SequentialAccess.
Lastly, I prefer to handle this type of thing using a simple System.Web.IHttpHandler (ASHX) over an System.Web.UI.Page (ASPX).
Try creating a file called HectorsHandler.ashx with the following content:
<%# WebHandler Language="C#" Class="HectorsApp.HectorsHandler" %>
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Web;
namespace HectorsApp
{
public class HectorsHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctxt)
{
// Request.QueryString["docid"].ToString();
//string DocumentID = Request.QueryString["DocumentID"].ToString();
string DocumentID = "9163736c-8064-11e8-ab16-2c44fd826130";
string SessionId = "91494483-8064-11e8-ab16-2c44fd826130";
//Connection and Parameters
SqlParameter param1 = null;
SqlParameter param2 = null;
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ProcessManagerConnectionString"].ToString()))
{
SqlCommand cmd = new SqlCommand("sp_getdoc", conn);
cmd.CommandType = CommandType.StoredProcedure;
param1 = new SqlParameter("#DocumentID", SqlDbType.NVarChar, 100);
param2 = new SqlParameter("#SessionId", SqlDbType.NVarChar, 100);
param1.Direction = ParameterDirection.Input;
param2.Direction = ParameterDirection.Input;
param1.Value = DocumentID;
param2.Value = SessionId;
cmd.Parameters.Add(param1);
cmd.Parameters.Add(param2);
//Open connection and fetch the data with reader
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if (reader.Read())
{
//
string doctype = reader["Extension"].ToString();
string docname = reader["Docname"].ToString();
//
ctxt.Response.BufferOutput = false;
ctxt.Response.Buffer = false;
ctxt.Response.ContentType = doctype;
ctxt.Response.AddHeader("Content-Disposition", "attachment; filename=" + docname);
//Code for streaming the object while writing
byte[] buffer = new byte[8040];
long dataIndex = 0;
while (ctxt.Response.IsClientConnected)
{
long bytesRead = reader.GetBytes(reader.GetOrdinal("Data"), dataIndex, buffer, 0, buffer.Length);
if (bytesRead == 0)
{
break;
}
ctxt.Response.OutputStream.Write(buffer, 0, (int)bytesRead);
ctxt.Response.OutputStream.Flush();
dataIndex += bytesRead;
}
}
}
}
}
public bool IsReusable
{
get { return false; }
}
}
}
Per the comments below, there is no longer need to clear any data since you now have full control over what is being output.
Note that because CommandBehavior.SequentialAccess is being used, columns must be read in order.
Is there any performance gain from CommandBehavior.SequentialAccess?

How to retrieve image from Mysql and read it directly in image control asp.net

I stored a image as a byte[] array as blob datatype in MySQL, but I cant find proper way to read that same picture the other way in my asp.net application in image control. In the table "slike" there are 3 columns - image, imagename, brTablice - I was searching for an answer really long and yet didn't find any answers. Here is my code:
protected void Button1_Click(object sender, EventArgs e)
{
string connectionString = "Server=localhost;Uid=Aleksa;port=3306;Pwd=pass;Database=projekat_automobili;";
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("SELECT image from slike where brTablice = 'BG-456-SD'", con);
con.Open();
MySqlDataReader DR1 = cmd.ExecuteReader();
if (DR1.Read())
{
//TextBoxJmbg.Text = DR1.GetString(DR1.GetOrdinal("jmbg"));
//TextBoxIP.Text = DR1.GetString(DR1.GetOrdinal("imeprezime"));
//TextBoxTel.Text = DR1.GetString(DR1.GetOrdinal("tel"));
byte[] imgg = (byte[])(DR1["image"]);
if (imgg == null)
{
MemoryStream mstream = new MemoryStream(imgg);
Image1.ImageUrl = System.Drawing.Image.FromStream(mstream).ToString();
Image1.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(imgg);
//Image1.ImageUrl = "";
}
else
{
MemoryStream mstream = new MemoryStream(imgg);
Image1.ImageUrl = System.Drawing.Image.FromStream(mstream).ToString();
}
}
con.Close();
}
this is part of project.
mysql table:
----------------------------
G_Picture| G_Picture_size |
----------------------------
0xsd/s45e| 9000 |
-----------------------------
uint FileSize = _sqldatareader.GetUInt32(_sqldatareader.GetOrdinal("G_Picture_size"));
byte[] rawData = new byte[FileSize];
_sqldatareader.GetBytes(_sqldatareader.GetOrdinal("G_Picture"), 0, rawData, 0, (Int32)FileSize);
MemoryStream ms = new MemoryStream(rawData);
__G_Picture.BackgroundImage = new Bitmap(ms);
Now you a bitmap picture.
hope this work.

How to retrieve image from Oracle database using C# web application?

I want to retrieve an image from an Oracle database to an Image control in asp.net. I tried but it's not working.
This is the code used for inserting image into database:
protected void btnUpload_Click(object sender, EventArgs e)
{
int imgLength = 0;
string imgContentType = null;
string imgFileName = null;
Stream imgStream = FileUpload.PostedFile.InputStream;
imgLength = FileUpload.PostedFile.ContentLength;
imgContentType = FileUpload.PostedFile.ContentType;
imgFileName = FileUpload.PostedFile.FileName;
if (imgContentType == "image/jpeg" || imgContentType == "image/gif" ||
imgContentType == "image/pjpeg"
|| imgContentType == "image/bmp")
{
OracleConnection DbConnection = new OracleConnection(con1);
DbConnection.Open();
FileStream fls;
fls = new FileStream(#imgFileName, FileMode.Open, FileAccess.Read);
byte[] blob = new byte[fls.Length];
fls.Read(blob, 0, System.Convert.ToInt32(fls.Length));
fls.Close();
string query = "insert into image(id,name,photo) values(1,'" + imgFileName + "'," + " :BlobParameter )";
// Establish a new OracleCommand
OracleCommand cmd = new OracleCommand();
cmd.CommandText = query;
cmd.Connection = DbConnection;
cmd.CommandType = CommandType.Text;
System.Data.OracleClient.OracleParameter paramImage = new System.Data.OracleClient.OracleParameter("image",
Oracle.DataAccess.Client.OracleDbType.Blob);
paramImage.ParameterName = "BlobParameter";
paramImage.Value = blob;
paramImage.Direction = ParameterDirection.Input;
cmd.Parameters.Add(paramImage);
cmd.ExecuteNonQuery();
}
Table:
Id Name Photo
1 C:\\user\pictures\animal.jpeg (BLOB)
Below is the code used to retrieve the image into an image control but this code is not working.
For the past two days I've been struggling with this
void GetImagesFromDatabase()
{
try
{
OracleConnection DbConnection = new OracleConnection(con1);
DbConnection.Open();
OracleCommand cmd = new OracleCommand("Select name,photo from Image", DbConnection);
OracleDataReader oda = cmd.ExecuteReader();
while (oda.Read())
{
string path = oda[0].ToString();
img.ImageUrl = path;
if(oda.GetValue(1).ToString() !=""){
FileStream fls;
fls = new FileStream(#path, FileMode.Open, FileAccess.Read);
byte[] blob = new byte[fls.Length];
fls.Read(blob, 0, System.Convert.ToInt32(fls.Length));
fls.Close();
MemoryStream memStream = new MemoryStream(blob);
img.ImageUrl = oda[2].ToString();
}
}
}
catch (Exception ex)
{
}
}
Any ideas? Thanks in advance
maybe this code can help you:
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}

Loading PictureBox Image From Database

i'm trying to load images from database to a PictureBox. I use these following codes in order to load them to my picture. I've written some code but don't know what I should do for continuing.
Any help will be appreciated.
private void button1_Click(object sender, EventArgs e)
{
sql = new SqlConnection(#"Data Source=PC-PC\PC;Initial Catalog=Test;Integrated Security=True");
cmd = new SqlCommand();
cmd.Connection = sql;
cmd.CommandText = ("select Image from Entry where EntryID =#EntryID");
cmd.Parameters.AddWithValue("#EntryID", Convert.ToInt32(textBox1.Text));
}
Continue with something like this in the button1_Click:
// Your code first, here.
var da = new SqlDataAdapter(cmd);
var ds = new DataSet();
da.Fill(ds, "Images");
int count = ds.Tables["Images"].Rows.Count;
if (count > 0)
{
var data = (Byte[])ds.Tables["Images"].Rows[count - 1]["Image"];
var stream = new MemoryStream(data);
pictureBox1.Image = Image.FromStream(stream);
}
Assuming we have a simple database with a table called BLOBTest:
CREATE TABLE BLOBTest
(
BLOBID INT IDENTITY NOT NULL,
BLOBData IMAGE NOT NULL
)
We could retrieve the image to code in the following way:
try
{
SqlConnection cn = new SqlConnection(strCn);
cn.Open();
//Retrieve BLOB from database into DataSet.
SqlCommand cmd = new SqlCommand("SELECT BLOBID, BLOBData FROM BLOBTest ORDER BY BLOBID", cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds, "BLOBTest");
int c = ds.Tables["BLOBTest"].Rows.Count;
if(c>0)
{ //BLOB is read into Byte array, then used to construct MemoryStream,
//then passed to PictureBox.
Byte[] byteBLOBData = new Byte[0];
byteBLOBData = (Byte[])(ds.Tables["BLOBTest"].Rows[c - 1]["BLOBData"]);
MemoryStream stmBLOBData = new MemoryStream(byteBLOBData);
pictureBox1.Image= Image.FromStream(stmBLOBData);
}
cn.Close();
}
catch(Exception ex)
{MessageBox.Show(ex.Message);}
This code retrieves the rows from the BLOBTest table in the database into a DataSet, copies the most recently added image into a Byte array and then into a MemoryStream object, and then loads the MemoryStream into the Image property of the PictureBox control.
Full reference guide:
http://support.microsoft.com/kb/317701
private void btnShowImage_Click(object sender, EventArgs e)
{
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\\PIS(ACU).mdb;";
Con = new OleDbConnection(#constr);
Con.Open();
Com = new OleDbCommand();
Com.Connection = Con;
Com.CommandText = "SELECT Photo FROM PatientImages WHERE Patient_Id = " + val + " ";
OleDbDataReader reader = Com.ExecuteReader();
if (reader.Read())
{
byte[] picbyte = reader["Photo"] as byte[] ?? null;
if (picbyte != null)
{
MemoryStream mstream = new MemoryStream(picbyte);
pictureBoxForImage.Image = System.Drawing.Image.FromStream(mstream);
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(mstream);
}
}
HERE IS A TOTAL ANOTHER WAY TO DO SO:
You can simply convert the Image to Text before saving it into DataBase and the then convert it back to the Image after reading it:
public string ImageToStringFucntion(Image img)
{
try
{
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] imgBytes = ms.ToArray();
string FinalText = Convert.ToBase64String(imgBytes, 0 , imgBytes.Length);
return FinalText;
}
}
catch
{
return null;
}
}
Now you can Insert or Update your Database...
Now Let's consider you want it back:
public Image StringToImage_(string input_)
{
try
{
byte[] imgBytes = Convert.FromBase64String(input_);
using (MemoryStream ms = new MemoryStream(imgBytes))
{
Image img = Image.FromStream(ms, true);
return img;
}
}
catch (Exception ex)
{
return null;
}
}
Now you can do as follow:
// Considering you have already pulled your data
// from database and set it in a DataSet called 'ds',
// and you picture is on the field number [1] of your DataRow
pictureBox1.Image = StringToImage_(ds.Table[0].Rows[0][1].ToString());

Convert from binary data to an image control in ASP.NET

I have binary data of an image in my database, and I want to display it in an image control in ASP.NET. How? If it is impossible, please find another way to save it in the database and display it in an image control.
Create a regular HTML img element like so:
<img runat="server" id="image" />
And in code behind do this:
image.src = "data:image/png;base64," + Convert.ToBase64String(imageBytes);
Where imageBytes is a byte[].
You are done. The image will be displayed.
Most likely the image is being stored as a byte array in the database. If so, then you can use this:
public static System.Drawing.Image ByteArrayToImage(byte[] bArray)
{
if (bArray == null)
return null;
System.Drawing.Image newImage;
try
{
using (MemoryStream ms = new MemoryStream(bArray, 0, bArray.Length))
{
ms.Write(bArray, 0, bArray.Length);
newImage = System.Drawing.Image.FromStream(ms, true);
}
}
catch (Exception ex)
{
newImage = null;
//Log an error here
}
return newImage;
}
public Byte[] Ret_image(Int32 id)
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select * from tbimage where imageid=#id";
cmd.Connection = con;
cmd.Parameters.Add("#id", SqlDbType.Int).Value = id;
SqlDataReader dr = cmd.ExecuteReader();
dr.Read();
Byte[] ar = (Byte[])(dr[1]);
dr.Close();
cmd.Dispose();
return ar;
}
protected void Button2_Click(object sender, EventArgs e)
{
Byte[] ar = Ret_image(Convert.ToInt32(TextBox2.Text));
String st = Server.MapPath("abc.jpg");
FileStream fs = new FileStream(st, FileMode.Create, FileAccess.Write);
fs.Write(ar, 0, ar.Length);
fs.Close();
Image1.ImageUrl = "abc.jpg";
}
Use this event for the button click to retrieve image and call the Ret_Image method here.
In a generic handler (.ashx):
public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if(!string.IsNullOrEmpty(context.Request.QueryString["ImageId"]))
{
try
{
string ImageId = context.Request.QueryString["ImageId"].ToString();
ImageDataModel idm = new ImageDataModel();
byte[] ImageData = idm.getImageData(ImageId);
context.Response.ContentType = "image/JPEG";
context.Response.OutputStream.Write(ImageData, 0, ImageData.Length);
}
catch(Exception ex){}
}
}
}
SqlConnection con = new SqlConnection();
string _path;
Using SYstem.IO;
Using System.Data.SQLClient;
//convert Image to binary and save in DB
private void button1_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
_path = openFileDialog1.FileName;
InsertInSQL(_path);
}
}
private void InsertInSQL(string _path)
{
con.ConnectionString = Pic.Properties.Settings.Default.ConnectionS;
string strQ = "insert into dbo.PicTBL(Pic)values(#p)";
SqlCommand command = new SqlCommand(strQ,con);
command.Parameters.AddWithValue("#p",ImageToBinary(_path));
con.Open();
command.ExecuteNonQuery();
con.Close();
}
public static byte[] ImageToBinary(string _path)
{
FileStream fS = new FileStream(_path, FileMode.Open, FileAccess.Read);
byte[] b = new byte[fS.Length];
fS.Read(b, 0, (int)fS.Length);
fS.Close();
return b;
}
//Convert Binary to imge and save in a folder
private void button1_Click_1(object sender, EventArgs e)
{
DataTable dt = Rimage();
foreach (DataRow row in dt.Rows)
{
byte[] b = (byte[])row["Pic"];
Image img = BinaryToImage(b);
img.Save("D:\\NewFolder\\" + row["ID"].ToString() + ".jpg");
}
}
private Image BinaryToImage(byte[] b)
{
if (b == null)
return null;
MemoryStream memStream = new MemoryStream();
memStream.Write(b, 0, b.Length);
return Image.FromStream(memStream);
}
private DataTable Rimage()
{
con.ConnectionString = Pic.Properties.Settings.Default.ConnectionS;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select * from dbo.PicTBL";
cmd.Connection = con;
SqlDataAdapter adp = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
con.Open();
adp.Fill(dt);
return dt;
}

Categories

Resources