After download/upload files from MS SQL, the files become unreadable - c#

I have ASP MVC app, MS SQL and C#. I download a file to MS SQL, then I upload the file from DB. After this the file become unreadable. I can't understand what happens. Below code, which returns the file to client.
public string CreateFile(HttpPostedFileBase file)
{
string stream_id = String.Empty;
try
{
int size = file.ContentLength;
string name = file.FileName;
string contentType = file.ContentType;
byte[] bytes = new byte[size];
file.InputStream.Read(bytes, 0, size);
string constr = ConfigurationManager.ConnectionStrings["PokrovConnectionString"].ConnectionString;
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection con = new SqlConnection(constr))
{
string query = "DECLARE #MyTableVar TABLE (stream_id uniqueidentifier);"
+ "INSERT INTO Files(name, file_stream) OUTPUT INSERTED.stream_id INTO #MyTableVar VALUES(#name, #file_stream);"
+ "SELECT TOP (1) #Identity = stream_id FROM #MyTableVar;";
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.Add("#name", SqlDbType.VarChar).Value = Path.GetFileName(file.FileName);
cmd.Parameters.Add("#file_stream", SqlDbType.VarBinary).Value = bytes;
SqlParameter idParam = cmd.Parameters.Add("#Identity", SqlDbType.NVarChar, 1000);
idParam.Direction = ParameterDirection.Output;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
stream_id = (string)idParam.Value;
}
}
ts.Complete();
}
}
catch { }
return stream_id;
}
public FileContentResult GetFile(Guid stream_id, string contentType = "application/octet-stream")
{
SqlDataReader rdr;
byte[] fileContent = null;
string mimeType = "";
string fileName = "";
string connect = onfigurationManager.ConnectionStrings["PokrovConnectionString"].ConnectionString;
bool success = false;
using (var conn = new SqlConnection(connect))
{
var qry = "SELECT file_stream, name, file_type FROM Files WHERE stream_id = #stream_id";
var cmd = new SqlCommand(qry, conn);
cmd.Parameters.AddWithValue("#stream_id", stream_id);
conn.Open();
try
{
rdr = cmd.ExecuteReader();
if (rdr.HasRows)
{
rdr.Read();
fileContent = (byte[])rdr["file_stream"];
mimeType = rdr["file_type"].ToString();
fileName = rdr["name"].ToString();
}
success = true;
}
catch
{
return null;
}
}
if (success == true)
{
FileContentResult newFile = new FileContentResult(fileContent, contentType);
newFile.FileDownloadName = fileName;
return newFile;
}
return null;
}

From looking at the code which stores posted file into database - most probably you forgot to copy actual file content, just initialized empty byte array with length of posted file, and saved it into db.
.Net has a class which can help you save stream into sql server without allocating buffer and reading entire stream first - SqlBytes. Try to replace this line:
byte[] bytes = new byte[file.ContentLength];
With this:
SqlBinary bytes = new SqlBinary(file.InputStream);
You can also take a look at SqlBinary usage in this post.

Related

how to retrieve img from MySQL into pictureBox

I want get an image from a Blob in MySQL then display image in a PictureBox. My incoming image is not correct and I don't understand how I can retrieve the byte array because my current array is not correct.
My code:
add img into database:
using(OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == DialogResult.OK)
{
byte[] bytes = File.ReadAllBytes(ofd.FileName);
imageUrl = ofd.FileName.ToString();
//roundPictureBox1.Image = Image.FromFile(ofd.FileName);
roundPictureBox2.ImageLocation = imageUrl;
MySqlConnection con = new MySqlConnection(connectionString);
con.Open();
MySqlCommand cmd = new MySqlCommand("INSERT INTO reg.img_table(image, id) VALUES (#image, #id)", con);
long id = cmd.LastInsertedId;
Properties.Settings.Default.idImg = id;
cmd.Parameters.AddWithValue("#image", bytes);
cmd.Parameters.AddWithValue("#id", id);
cmd.ExecuteNonQuery();
con.Close();
}
}
return Img:
private Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
main code:
private void photoLoad()
{
string connectionString = "datasource=localhost;" +
"port=3306;" +
"database=reg;" +
"username=root;" +
"password=Admin123";
MySqlConnection con = new MySqlConnection(connectionString);
byte[] ImageByte = new byte[0];
string query1 = "select image from reg.img_table where id= #id";
MySqlCommand cmd = new MySqlCommand(query1, con);
cmd.Parameters.AddWithValue("#id", Properties.Settings.Default.idImg);
try
{
con.Open();
MySqlDataReader row;
row = cmd.ExecuteReader();
while (row.Read())
{
ImageByte = (Byte[])(row["image"]);
}
if (ImageByte != null)
{
// You need to convert it in bitmap to display the image
roundPictureBox1.Image = byteArrayToImage(ImageByte);
roundPictureBox1.Refresh();
}
}
catch (Exception ex)
{
MessageBox.Show("Error Img");
}
}
An error doesn't show. The login form shows but PictureBox doesn't show the photo.
According to your OP, you're storing your image in a database BLOB column in a MySql database. The following shows how to insert an image into a MySql database table. Then retrieve that image and display it in a PictureBox.
Download/install NuGet package: MySql.Data
Database Table: Student
I've chosen to store the connection string for the database in App.config.
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="MySqlConnectionString" connectionString="Server=localhost;Port=3306;Database=University123;Uid=testAdmin;Pwd=password123;" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>
Create a class: (name: HelperMySql.cs)
In VS menu, click Project
Select Add Class...
Add the following using statements:
using System.Configuration;
using System.IO;
using MySql.Data.MySqlClient;
HelperMySql.cs
Note: I've chosen to use LongBlob instead of Blob - this can be changed, if desired.
public class HelperMySql
{
private string _connectionStr = ConfigurationManager.ConnectionStrings["MySqlConnectionString"].ConnectionString;
//private string _connectionStr = "Server=localhost;Port=3306;Database=University123;Uid=testAdmin;Pwd=password123;";
public void ExecuteNonQuery(string sqlText)
{
using (MySqlConnection con = new MySqlConnection(_connectionStr))
{
//open
con.Open();
using (MySqlCommand cmd = new MySqlCommand(sqlText, con))
{
//execute
cmd.ExecuteNonQuery();
}
}
}
public byte[] GetImageAsByteArray(string filename)
{
//reads image from file and returns as byte[]
if (String.IsNullOrEmpty(filename))
throw new Exception("Error (GetImageAsByteArray) - Filename not specified.");
else if(!File.Exists(filename))
throw new Exception($"Error (GetImageAsByteArray) - File '{filename}' doesn't exist.");
return System.IO.File.ReadAllBytes(filename);
}
public void TblStudentCreate()
{
//for mySQL, use backticks (ex: `First Name`) if tablename has space in it
string sqlText = #"CREATE TABLE Student (Id int NOT NULL AUTO_INCREMENT,
FirstName varchar(50),
LastName varchar(75),
Img longblob,
CONSTRAINT PK_Student_ID PRIMARY KEY(ID));";
ExecuteNonQuery(sqlText);
Debug.WriteLine("Info: Table created (Student)");
}
public void TblStudentInsert(string firstName, string lastName, string filename)
{
if (String.IsNullOrEmpty(filename))
throw new Exception("Error (TblStudentInsert) - Filename not specified.");
else if (!File.Exists(filename))
throw new Exception($"Error (TblStudentInsert) - File '{filename}' doesn't exist.");
byte[] imageBytes = File.ReadAllBytes(filename);
TblStudentInsert(firstName, lastName, imageBytes);
}
public void TblStudentInsert(string firstName, string lastName, byte[] imageBytes)
{
string sqlText = "INSERT INTO Student (FirstName, LastName, Img) VALUES (#firstName, #lastName, #imageBytes);";
using (MySqlConnection con = new MySqlConnection(_connectionStr))
{
//open
con.Open();
using (MySqlCommand cmd = new MySqlCommand(sqlText, con))
{
//add parameters
//FirstName
if (!String.IsNullOrEmpty(firstName))
cmd.Parameters.Add("#firstName", MySqlDbType.VarChar).Value = firstName;
else
cmd.Parameters.Add("#firstName", MySqlDbType.VarChar).Value = DBNull.Value;
//LastName
if (!String.IsNullOrEmpty(lastName))
cmd.Parameters.Add("#lastName", MySqlDbType.VarChar).Value = lastName;
else
cmd.Parameters.Add("#lastName", MySqlDbType.VarChar).Value = DBNull.Value;
//Img
if (imageBytes != null)
cmd.Parameters.Add("#imageBytes", MySqlDbType.LongBlob).Value = imageBytes;
else
cmd.Parameters.Add("#imageBytes", MySqlDbType.LongBlob).Value = DBNull.Value;
//execute
cmd.ExecuteNonQuery();
}
}
}
public byte[] GetStudentImage(int id)
{
string sqlText = "SELECT img from Student where Id = #id;";
using (MySqlConnection con = new MySqlConnection(_connectionStr))
{
//open
con.Open();
using (MySqlCommand cmd = new MySqlCommand(sqlText, con))
{
cmd.Parameters.Add("#id", MySqlDbType.Int32).Value = id;
//execute
using (MySqlDataReader dr = cmd.ExecuteReader())
{
if (dr.HasRows)
{
while(dr.Read())
{
//get image from database and return as byte[]
if (dr["Img"] != null && dr["Img"] != DBNull.Value)
return (byte[])dr["Img"];
}
}
}
}
}
return null;
}
}
Usage: Insert Record to Database
private HelperMySql helper = new HelperMySql();
...
helper.TblStudentInsert("John", "Smith", #"D:\Images\Students\JohnSmith.png");
Usage: Display Image in PictureBox (name: pictureBox1)
int studentId = 1;
byte[] imageBytes = helper.GetStudentImage(studentId);
using (MemoryStream ms = new MemoryStream(imageBytes))
{
pictureBox1.Image = Image.FromStream(ms);
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; //fit to size
pictureBox1.Refresh();
}
Note: You may consider storing the filenames in the database, and store the actual files in the file system instead.
Resources:
MySQL 8.0 Reference Manual
Data Type Storage Requirements

Opening the varbinary column in a popup window using contenttype

I am making a file uploader using html tags. I have id, Name and Data in my table. Data is storing the contents of the file in binary format in a column of datatype varbinary(max). I am able to successfully upload the file and I am also able to read the byte array back.
Code for upload at code behind:
protected void Upload(object sender, EventArgs e)
{
string filename = Path.GetFileName(FileUpload1.PostedFile.FileName);
string contentType = FileUpload1.PostedFile.ContentType;
using (Stream fs = FileUpload1.PostedFile.InputStream)
{
using (BinaryReader br = new BinaryReader(fs))
{
byte[] bytes = br.ReadBytes((Int32)fs.Length);
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
string query = "insert into FileUploader2 values (#Name, #ContentType, #Data)";
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#Name", filename);
cmd.Parameters.AddWithValue("#ContentType", contentType);
cmd.Parameters.AddWithValue("#Data", bytes);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
Context.Response.Write("Uploaded Successfully!");
}
}
}
}
Response.Redirect(Request.Url.AbsoluteUri);
}
I am also creating a grid which shows me list of files along with an icon which when clicked will view me the file after reading the byte array. I have a JS function on that onclick which I am accessing through WebMethod at code-behind. Following is my code when user clicks on view icon:
[System.Web.Services.WebMethod]
public static void ShowDocument()
{
string filename = string.Empty;
string contentType = string.Empty;
byte[] bytes = null;
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
con.Open();
using (SqlCommand com = new SqlCommand("SELECT * FROM FileUploader2", con))
{
using (SqlDataReader reader = com.ExecuteReader())
{
if (reader.Read())
{
filename = (string)reader["Name"];
contentType = (string)reader["ContentType"];
bytes = (byte[])reader["Data"];
}
}
}
}
System.Web.HttpContext.Current.Response.ContentType = contentType;
System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;
filename=" + filename);
System.Web.HttpContext.Current.Response.OutputStream.Write(bytes, 0, bytes.Length);
System.Web.HttpContext.Current.Response.Flush();
}
This code is working fine as well and correctly reads all the columns. Now after reading, I want to view the file as well in a pop window. How can I do so? I think I have to take contenttype to let it know what type of file I want to open and then use the bytes to do so. But I have no idea how to achieve that.

Loop through multiple files in temp directory and insert files into MS SQL database with existing rows/id's

I have a SQL database with existing rows and attachment ID's. I have a folder of several thousand PDF files that need to be inserted into this database. The files should be inserted in each row based on filename/column.
Example. One file is called 123.pdf that should be inserted in the row with the ID of 123.
I have created an Asp.net web forms application using the Ajax File Upload tool. It works fine if I use a real directory. How can I do this with a temporary Directory?
protected void AjaxFileUpload1_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
try
{
string filePath = e.FileName;
string filename = Path.GetFileName(filePath);
string ext = Path.GetExtension(filename);
string contenttype = String.Empty;
switch (ext)
{
case ".pdf":
contenttype = "application/pdf";
break;
}
if (contenttype != String.Empty)
{
string tempPath = System.IO.Path.GetTempFileName();
AjaxFileUpload1.SaveAs(tempPath);
using (FileStream fs = File.OpenRead(tempPath))
{
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
//How do I create a temp directory of the files in the AjaxFileUploader?
var dir = new DirectoryInfo(CreateTempDirectoryHere);
FileInfo[] pdfFiles = dir.GetFiles();
foreach (FileInfo pdfFile in pdfFiles)
{
var attachmentID = Path.GetFileNameWithoutExtension(pdfFile.ToString());
string constr = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
SqlCommand cmd = new SqlCommand("dbo.spUploadContentBulk", con);
cmd.Parameters.AddWithValue("#AttachmentID", attachmentID);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter()
{
ParameterName = "#FileName",
Value = filename
});
cmd.Parameters.Add(new SqlParameter()
{
ParameterName = "#FileContent",
Value = bytes
});
cmd.Parameters.Add(new SqlParameter()
{
ParameterName = "#FileType",
Value = contenttype
});
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
File.Delete(tempPath);
}
}
catch (Exception ex)
{
txtError.Text = ex.ToString();
}
}
I mean something more like this (don't even use a temp folder):
protected void AjaxFileUpload1_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
try
{
string filename = e.FileName;
var bytes = e.GetContents();
var attachmentID = Path.GetFileNameWithoutExtension(fileName);
string ext = Path.GetExtension(filename);
string contenttype = String.Empty;
switch (ext)
{
case ".pdf":
contenttype = "application/pdf";
break;
}
if (contenttype != String.Empty)
{
string constr = ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
SqlCommand cmd = new SqlCommand("dbo.spUploadContentBulk", con);
cmd.Parameters.AddWithValue("#AttachmentID", attachmentID);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter()
{
ParameterName = "#FileName",
Value = filename
});
cmd.Parameters.Add(new SqlParameter()
{
ParameterName = "#FileContent",
Value = bytes
});
cmd.Parameters.Add(new SqlParameter()
{
ParameterName = "#FileType",
Value = contenttype
});
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
catch (Exception ex)
{
txtError.Text = ex.ToString();
}
}

Why I am getting one more character?

Hello Im using this C# code for images upload.
protected void UploadFile(object sender, EventArgs e)
{
string filename = Path.GetFileName(FileUpload1.PostedFile.FileName);
string contentType = FileUpload1.PostedFile.ContentType;
using (Stream fs = FileUpload1.PostedFile.InputStream)
{
using (BinaryReader br = new BinaryReader(fs))
{
byte[] bytes = br.ReadBytes((Int32)fs.Length);
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (MySqlConnection con = new MySqlConnection(constr))
{
string query = "INSERT INTO foto(FileName, ContentType, Content) VALUES (#FileName, #ContentType, #Content)";
using (MySqlCommand cmd = new MySqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#FileName", filename);
cmd.Parameters.AddWithValue("#ContentType", contentType);
cmd.Parameters.AddWithValue("#Content", bytes);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
}
Response.Redirect(Request.Url.AbsoluteUri);
}
I upload the image in a longblob field, then to show the image I am using C# WebService, AJAX, JavaScript, converting the image to Base64String but image is displayed like if do not exist.
Here is my Base64String:
Base64String
As you can see the problem is with this extra characters:
AAEAAAD/////AQAAAAAAAAAPAQAAAHgBAAAC
Why this happen? And how can I solve it?
can you replace the bellowed lines with your above code
protected void UploadFile(object sender, EventArgs e)
{
string filename = Path.GetFileName(FileUpload1.PostedFile.FileName);
string contentType = FileUpload1.PostedFile.ContentType;
using (Stream fs = FileUpload1.PostedFile.InputStream)
{
using (BinaryReader br = new BinaryReader(fs))
{
System.Drawing.Image imagetuUpload = System.Drawing.Image.FromStream(fs);
Bitmap bitmap = new Bitmap(imagetuUpload);
System.IO.MemoryStream stream = new MemoryStream();
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Position = 0;
byte[] upproimag = new byte[stream.Length + 1];
stream.Read(upproimag, 0, upproimag.Length);
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (MySqlConnection con = new MySqlConnection(constr))
{
string query = "INSERT INTO foto(FileName, ContentType, Content) VALUES (#FileName, #ContentType, #Content)";
using (MySqlCommand cmd = new MySqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#FileName", filename);
cmd.Parameters.AddWithValue("#ContentType", contentType);
cmd.Parameters.AddWithValue("#Content", upproimag);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
}
}
Response.Redirect(Request.Url.AbsoluteUri);
}
i hop it may help you :)
long time back i was in same issue i do not remember other than doing this at that time:
I check if I am wrong or not going here:
http://jsfiddle.net/hpP45/
I try to decode first(google bse64 decoder )
https://www.base64decode.org/
and save decoded binary data as an jpeg file and open it.
if it does not open then i guess,there might be issue on your base64 encoding

How to retrieve image from oracle database?

I want to retrieve image from oracle database
and show it in Image control I tried but it is showing empty image
Code for Insert Image:
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:\Document\Image\Ocean.jpeg (BLOB)
In the below code I'm trying to retrieve and show that image in image control
but it's not working
Code for retrieve:
void GetImagesFromDatabase()
{
try
{
OracleConnection DbConnection = new OracleConnection(con1);
DbConnection.Open();
OracleCommand cmd = new OracleCommand("Select name from Image", DbConnection);
OracleDataReader oda = cmd.ExecuteReader();
while (oda.Read())
{
string path = oda[0].ToString();
img.ImageUrl = path;
}
}
catch (Exception ex)
{
}
}
Any ideas? Thanks in advance

Categories