Display.ashx not displaying image name with character & - c#

I have a situation where Display.ashx displays successfully images from Sql server with only letters(e.g Coffee or Green tea) in it but when a image name is saved as (Coffee & Froth) it does not display.please see code below,i placed a break point on Img in Display class and when the imagename is Coffee the full string is passed but when the image name is Coffee & Froth it cuts the froth and only takes Coffee,meaning it takes only the string before the character &.can someone please please show me a workaround so it takes the whole string with the character.Thanks
public class Display : IHttpHandler
{
public Stream Displays(string Img)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DB"].ConnectionString.ToString()))
{
string sql = string.Format("select top 1 img from Images where Name = '{0}'", Img);
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.CommandType = CommandType.Text;
cmd.Connection.Open();
object imagevalue = cmd.ExecuteScalar();
if (imagevalue != null && imagevalue != DBNull.Value)
{
return new MemoryStream((byte[])imagevalue);
}
using (FileStream fs = File.OpenRead(HttpContext.Current.Server.MapPath(#"~/Content/noimage.png")))
{
MemoryStream memStream = new MemoryStream();
memStream.SetLength(fs.Length);
fs.Read(memStream.GetBuffer(), 0, (int)fs.Length);
return memStream;
}
}
}
#endregion
This is how i call the Image
protected void Refresh_SelectedIndexChanged(object sender, EventArgs e)
{
// string id = CoffeeMenu.SelectedValue;
Image1.ImageUrl = "~/Display.ashx?id=" + "Coffee & Froth";
divSuccess.Visible = false;
divError.Visible = false;
}
HTML
<asp:DropDownList ID="CoffeeMenu" runat="server" CssClass="selectpicker" OnSelectedIndexChanged="Refresh_SelectedIndexChanged"/>

Encode the data part:
Image1.ImageUrl = "~/Display.ashx?id=" + Server.UrlEncode("Coffee & Froth");
The problem you have is that an & is used to split values in a url so extra parameters for your display would look like:
?name=blah&resize=1920x1080&convert=png&rotate=90
As such your "Coffee & Froth" is probably being requested by the browser as Coffee+&+Froth and is being received and interpreted by your ashx as having these parameters:
{
"id": "Coffee ",
" Froth": null
}
Or, strip anything that's not a number or letter out of the filename; looks like you're in control of the naming of these things as they're stored on disk so make life simple

(moving comment to answer)
Try Coffee & Froth or Coffee%20%26%20Froth
& is used in HTML to represent &
%20 is hexadecimal for space and %26 is hexadecimal for &. Hexadecimal is often used to encode special characters in URLs.
Full ASCII table:
https://en.wikipedia.org/wiki/ASCII#Printable_characters

Related

Sql Stored Procedure to csv file with Timestamp

The application stores results from a SQL stored procedure into a given csv. It is necessary for the file to have a timestamp within the filename. I haven't been successful finding the solution through any of my research. Here's the code, keep in mind that the timestamp needs to have the date and most importantly the time 'hh:ss'
string db = "databasename";
string startTime = "2018-04-17 00:00:00.000";
string endTime = "2018-04-17 23:59:59.997";
string LiquorFile = "LiquorFile.csv";
using (SqlConnection con = new SqlConnection(GlobalConfig.CnnString(db)))
{
var tableName = "liqTemp";
var fileName = tableName + ".csv";
var recordCount = 0;
var fileCount = 0;
SqlCommand scCmd = new SqlCommand("dbo.spGetInventory_Liquor", con);
scCmd.CommandType = CommandType.StoredProcedure;
SqlDataReader reader;
con.Open();
scCmd.Parameters.Add("#StartDate", SqlDbType.DateTime).Value = startTime;
scCmd.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = endTime;
reader = scCmd.ExecuteReader();
StreamWriter writer = null;
try
{
while (reader.Read())
{
if (writer == null || recordCount == 50000)
{
if (writer != null)
{
writer.Close();
writer.Dispose();
}
fileName = tableName + "_" + (++fileCount).ToString() + ".csv";
writer = new StreamWriter(fileName);
}
recordCount++;
writer.WriteLine("\t{0}\t{1}", reader.GetDecimal(0), reader.GetString(1));
}
reader.NextResult();
}
finally
{
if (writer != null)
{
writer.Dispose();
}
}
}
Brainstorming through this implementation I believe this can be incorporated somehow through the start and end time string.
I'm still thinking of a proper title for this question.
Appears that you want to store some metadata along with the raw CSV data. Some file types, depending on the file type, have loads of metadata properties like authorship and company name etc. So, in this situation, I might elect to store my CSV data in XSLX format using the amazing ClosedXML library. The XSLX file type has lots of metadata properties to store your timestamps and many more.
Below is an example adding properties to a Docx file. This just shows that Microsoft office formats have lots of available metadata properties you can access and use.
How to set extended file properties?
using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;
string filePath = #"C:\temp\example.docx";
var file = ShellFile.FromFilePath(filePath);
// Read and Write:
string[] oldAuthors = file.Properties.System.Author.Value;
string oldTitle = file.Properties.System.Title.Value;
file.Properties.System.Author.Value = new string[] { "Author #1", "Author #2" };
file.Properties.System.Title.Value = "Example Title";
// Alternate way to Write:
ShellPropertyWriter propertyWriter = file.Properties.GetPropertyWriter();
propertyWriter.WriteProperty(SystemProperties.System.Author, new string[] { "Author" });
propertyWriter.Close();
Think its just a simple use of current date formatting.
fileName = tableName + "_" + DateTime.Today.ToString("yyyyMMddHHmmss") + ".csv";
where the format is whatever you need - date, time, ticks, etc - whatever you need to get the granularity you desire. You can go to a formt string of "o" to get it down to decimal sub-seconds if you need to.

Programatically adding a dynamic number of spaces to a string

I've got a treeview control, which I want to look like this:
Just by messing around with css and a text string, I'm actually pretty close. I just need some help getting over the line.
Here is the code I'm using to generate the treeview:
void FillTree_Parent()
{ // fills the parent view of the Tree Action items
//int RoleID = Convert.ToInt32(ddlRole.SelectedValue);
using (SqlConnection con4 = new SqlConnection(ConfigurationManager.ConnectionStrings["PBRConnectionString"].ConnectionString))
{
try
{
SqlCommand cmd2 = new SqlCommand("SELECT [ACCT_GRP], [ACCT_GRP_PK], [ACTIVE_FLG], [LOAD_BY], [LOAD_TIMESTAMP] FROM [ACCT_GRP_LIST] ORDER BY [ACCT_GRP] ASC", con4);
SqlDataAdapter da = new SqlDataAdapter(cmd2);
DataSet PrSet = new DataSet();
da.Fill(PrSet, "ACCT_GRP");
TreeViewAccts.Nodes.Clear();
foreach (DataRow dr in PrSet.Tables[0].Rows)
{
DateTime date = DateTime.Parse(dr["LOAD_TIMESTAMP"].ToString());
string formatted = date.ToString("MM/dd/yyyy");
TreeNode tnParent = new TreeNode();
// Here is our focus
tnParent.Text = dr["ACCT_GRP"].ToString().Replace("'", "''") +
" ········· " + "Active:" + dr["ACTIVE_FLG"].ToString() +
" ········· " + "Loaded On:" + formatted + "";
//
tnParent.Value = dr["ACCT_GRP_PK"].ToString();
tnParent.PopulateOnDemand = true;
tnParent.SelectAction = TreeNodeSelectAction.SelectExpand;
TreeViewAccts.Nodes.Add(tnParent);
FillTree_Child(tnParent, tnParent.Value);
}
}
catch (Exception ae)
{
Response.Write(ae.Message);
}
}
}
In that block marked "// Here is our focus", what I need to do is figure out how to get that first set of " ········· " to generate a dynamic number of spaces based on the fact that dr["ACCT_GRP"] can have as many as 75 characters. So, I need to determine the length of dr["ACCT_GRP"], subtract that from 75 and then generate that many spaces.
Can anyone help me with this logic? Also, as a bonus question, if anyone could tell me how to use spaces instead of "·"'s I'd appreciate it; whenever I just hit the spacebar a bunch of times and enclose it in quotes, it acts like those spaces don't even exist.
int len = dr["ACCT_GRP"].Length;
int paddingLength = 75 - len;
string padding = new string('.', paddingLength);
I get it from your question that you are viewing this in a browser (you mentioned CSS). HTML spec tells the browser to collapse all consecutive whitespace into a single space. You can use the "non-breaking space" character instead. It may be written as "&nbs p;" in HTML (minus the space between s and p) or using its Unicode representation 00 A0. So your c# code becomes:
int len = dr["ACCT_GRP"].Length;
int paddingLength = 75 - len;
string padding = new string('\u00A0', paddingLength);

Upload and download files on SQL Server from a C# application

I have a C# application that is uploading files to a sql server, I use this code to get the pdf file and then I change it to "bytes" for upload on the SQL Server database.
private void mButtonAddCV_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "PDF Files | *.pdf";
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if (openFileDialog1.FileName.Length > 0)
{
pathCV = openFileDialog1.FileName;
}
}
// Read the file and convert it to Byte Array
string filePath = pathCV;
string contenttype = String.Empty;
contenttype = "application/pdf";
if (contenttype != String.Empty)
{
Stream fs = File.OpenRead(filePath);
BinaryReader br = new BinaryReader(fs);
bytes = br.ReadBytes((Int32)fs.Length);
}
}
I use the code below to upload the file:
if (!mConnector.Update("INSERT INTO **** (***, ***, CV) " +
"VALUES ('" + *** + "', '" + *** + "', '" + bytes + "')"))
{
Messages.errorMessageBox("This CV already exists.");
}
else
{
ChangeScreen(ActiveScreen, ActiveScreens.ActiveScreen_CVList);
}
But now I don't know how to download this file and how to make a pdf file with the data stored on the database to see it. Can anyone help me?
Thanks!
First off, let's change the way you are forming your insert statement so you aren't opening up your system to sql injection. This will also make the insert statement easier to work with
var command = new SqlCommand("INSERT INTO myTable (x, y, z) VALUES (#a, #b, #c)", sqlConnection);
command.Parameters.Add(new SqlParameter("#a", bytes));
command.Parameters.Add(new SqlParameter("#b", bValue));
command.Parameters.Add(new SqlParameter("#c", bValue));
var resultingRows = command.ExecuteNonQuery();
To read the data out, use ExecuteReader, then the File object to save it to the disk.
var command = new SqlCommand("Select a from myTable", sqlConnection);
var reader = command.ExecuteReader();
reader.Read();
var pdfBinaryBuffer = (byte[])reader[0];
// Save file to disk
var file = File.Create("myFile.pdf", pdfBinaryBuffer.Length);
file.Write(pdfBinaryBuffer, 0, pdfBinaryBuffer.Length);
file.Close();
I suggest you to insert your byte data using SqlParameters...
see Inserting a byte array into sql server
Then, read the record using SqlDataReader's GetBytes(...) function see here.
I suggest you to upload pdf and save it in separate folder. you can save the path in database table that I think it is good.
Here is code for file upload
Drag “Fileupload” control to .aspx page (Use this code is for save .PDF to folder)
protected void fileUpload()
{
if (fileUp.HasFile)
{
fileUp.SaveAs(Server.MapPath("~/PoPDF/" + this.txtCusPo.Text +".PDF"));
string imgPrintPo = this.txtCusPo.Text + ".PDF";
}
}
Here is code for file download
You can put this code in button event but here I have used GridView row command event.
protected void gridview_RowCommand(object sender, GridViewCommandEventArgs e)
{
GridViewRow row = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);
if (e.CommandName == "SelectDownload")
{
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition", "filename=" + e.CommandArgument);
Response.TransmitFile(Server.MapPath("~/PoPDF/") + e.CommandArgument);
//Response.Flush();
Response.End();
}
}

storing image inside db using winforms

I want to save Image inside SqlServer using c# winforms and dapper micro orm.
Photo field inside db is of type VARBINARY(MAX)
Inside Book entity I have Photo property of type byte[].
public Book
{
...
public byte[] Photo { get; set; }
}
Inside winforms Window I have
OpenFileDialog open = new OpenFileDialog() { Filter = "Image Files(*.jpeg;*.bmp;*.png;*.jpg)|*.jpeg;*.bmp;*.png;*.jpg" };
if (open.ShowDialog() == DialogResult.OK)
{
txtPhoto.Text = open.FileName;
}
string image = txtPhoto.Text;
Bitmap bmp = new Bitmap(image);
FileStream fs = new FileStream(image, FileMode.Open, FileAccess.Read);
byte[] bimage = new byte[fs.Length];
fs.Read(bimage, 0, Convert.ToInt32(fs.Length));
fs.Close();
byte[] Photo = bimage;
// inside my repository I have error on saving object at line Photo = #Photo
var sql = "UPDATE Book " +
"SET Title = #Title, " +
" Language = #Language, " +
....
" Photo = #Photo" +
"WHERE Id = #Id";
this.db.Execute(sql, book); // error occures
return book;
Error is
A first chance exception of type 'System.Data.SqlClient.SqlException'
occurred in System.Data.dll
Additional information: Incorrect syntax near 'Photo'.
Am I missing something?
Thanks
You are missing white space before WHERE keyword:
" Photo = #Photo" + // no space at the end here
"WHERE Id = #Id"; // and no space before WHERE here
Also I suggest you to use multiline string (i.e. verbatim string literal) for sql query text (that makes query more readable):
var sql = #"UPDATE Book
SET Title = #Title,
Language = #Language,
Photo = #Photo
WHERE Id = #Id";
And one more thing - it's better to wrap Stream usage into using block (in order to release file handle in case of exception):
byte[] photo;
using(var stream = File.OpenRead(txtPhoto.Text)
{
photo = new byte[stream.Length];
stream.Read(photo, 0, photo.Length);
}
// db query with dapper is OK

Error while saving binary image from database to folder

I need to retrieve an image from a database and save it to disk. In the database, the image is stored in binary format but datatype of the column is varchar(5000).
This is the code that I am using for retrieving the image and saving it to disk
public void CreateImageDataUsingDataReader_ForNetezzaDB()
{
string strDbConn = string.Empty;
string strImageFileName = string.Empty;
string strImageData = string.Empty;
string strImgSavePath = string.Empty;
string strQuery = string.Empty;
Byte[] byteImageData;
MemoryStream stmImageData = new MemoryStream();
Image saveImage;
try
{
//---open the database connection
strDbConn = ConfigurationSettings.AppSettings["NetezzaDBConnection"].ToString().Trim();
OleDbConnection dbcon = new OleDbConnection(strDbConn);
dbcon.Open();
strQuery = "select name,signature_vod__c from sfb_call2_vod where signature_vod__c is not null limit 10";
OleDbCommand cmdSelect = new OleDbCommand(strQuery, dbcon);
OleDbDataReader imageReader = cmdSelect.ExecuteReader();
if (imageReader.HasRows)
{
while (imageReader.Read())
{
strImageFileName = imageReader["name"].ToString().Trim();
strImageData = imageReader["signature_vod__c"].ToString().Trim();
stmImageData.Seek(0, SeekOrigin.Begin);
//converting string to byte array
byteImageData = Convert.FromBase64String(strImageData);
//---create Memory stremm from the Image Byte data
stmImageData.Write(byteImageData, 0, byteImageData.Length);
//--saving the image
//saveImage = Image.FromStream(stmImageData);
using (saveImage = Image.FromStream(stmImageData))
{
strImgSavePath = ConfigurationSettings.AppSettings["ImageSavePath"].ToString().Trim();
saveImage.Save(strImgSavePath + strImageFileName + ".png", System.Drawing.Imaging.ImageFormat.Png); ///---error comes in this line
}
}
}
imageReader.Close();
dbcon.Close();
stmImageData.Close();
stmImageData = null;
}
catch (Exception ex)
{
throw new Exception("Error Occured in method CreateImageDataUsingDataReader " + ex.Message);
}
}
but I keep getting an error:
A generic error occurred in GDI+.
Same code if I execute for SQL Server database it works fine but issue comes only with the Netezza database
Please help me resolve this issue
You mention that you store the binary image in a varchar column. This and the fact that it works on an other db technology makes it obious that you read different data back in the Netazza case.
I would suggest to setup a testproject where you persist the same image to the 2 different databases (netazza and mssql), read it back from both a do a bitwise comparison of the result either between the db results or between original and read from db.
I would be surprised if you get the same result and if I am right, you should probalaby consider to use a binary data type to persist the image data in your db backend.

Categories

Resources