i have DataSet that contain Image.
i need to save this Image to File.
i try this:
SQL = ItemCode,PIC from ROW;
dsView = new DataSet();
adp = new SqlCeDataAdapter(SQL, Conn);
adp.Fill(dsView, "ROW");
adp.Dispose();
foreach (DataRow R in dsROW.Tables[0].Rows)
{
ItemCode = R["ItemCode"].ToString().Trim() ;
TEMP = R["PIC"].ToString().Trim();
Image image = R["PIC"] as Image;
if(image != null)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] imagedata = ms.ToArray();
}
but image Always is null
and in TEMP i see System.Byte[]
need some help, thanks
Your R["PIC"] is an array or Bytes.
First, you try to apply ToString() to it, and you simply get System.Byte[].
Then, you try to cast it to Image. How is Byte[] supposed to cast to Image?
You need to create an Image from your Byte array:
dsView = new DataSet();
adp = new SqlCeDataAdapter(SQL, Conn);
adp.Fill(dsView, "ROW");
adp.Dispose();
foreach (DataRow R in dsROW.Tables[0].Rows)
{
ItemCode = R["ItemCode"].ToString().Trim();
using (var ms = new MemoryStream(R["PIC"]))
{
Image image = Image.FromStream(ms);
image.Save($"C:\\Output\\YourCustomPath\\{ItemCode}.jpeg", ImageFormat.Jpeg);
}
}
You need to read the data in sequential access mode. Here is an example I use to read binary data. See the use of
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
snippet:
string sql = "Select file_data from utils where util_id="+uID.ToString()+";";
SqlCommand cmd = new SqlCommand(sql, database._sqlConnection);
SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess); // CommandBehavior.SequentialAccess: read columns in order and every column only once!
int columnNr = 0;
byte[] filedata = null;
try
{
while (rdr.Read())
{
//load the binary data
if (rdr.IsDBNull(columnNr)) //is there any binary data? //LAST COLUMN!!!!!
filedata = null;
else
{
//read binary data
int bufferSize = 100; // Size of the BLOB buffer.
byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes.
long retval; // The bytes returned from GetBytes.
long startIndex = 0; // The starting position in the BLOB output.
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
// Reset the starting byte for the new BLOB.
startIndex = 0;
// Read the bytes into outbyte[] and retain the number of bytes returned.
retval = rdr.GetBytes(columnNr, startIndex, outbyte, 0, bufferSize);
// Continue reading and writing while there are bytes beyond the size of the buffer.
while (retval >0) //== bufferSize)
{
bw.Write(outbyte);
bw.Flush();
// Reposition the start index to the end of the last buffer and fill the buffer.
startIndex += bufferSize;
retval = rdr.GetBytes(columnNr, startIndex, outbyte, 0, bufferSize);
}
bw.Close();
filedata = ms.ToArray();
ms.Close();
}
}
}
catch (SqlException ex)
Related
Hello I have been following numerous tutorials online for a new project I'm working on. I am obtaining my data from filestream and I'm getting an out of memory exception at this line:
byte[] buffer = new byte[(int)sfs.Length];
What I'm doing is immediately taking the byte array and then wanting to save it to the disc. If there is not an easy way to avoid the system out of memory exception, is there a way to write to disc from the sqlFileStream avoiding creating a new byte array?
string cs = #”Data Source=<your server>;Initial Catalog=MyFsDb;Integrated Security=TRUE”;
using (SqlConnection con = new SqlConnection(cs))
{
con.Open();
SqlTransaction txn = con.BeginTransaction();
string sql = “SELECT fData.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT(), fName FROM MyFsTable”;
SqlCommand cmd = new SqlCommand(sql, con, txn);
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
string filePath = rdr[0].ToString();
byte[] objContext = (byte[])rdr[1];
string fName = rdr[2].ToString();
SqlFileStream sfs = new SqlFileStream(filePath, objContext, System.IO.FileAccess.Read);
**byte[] buffer = new byte[(int)sfs.Length];**
sfs.Read(buffer, 0, buffer.Length);
sfs.Close();
string filename = #”C:\Temp\” + fName;
System.IO.FileStream fs = new System.IO.FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Write);
fs.Write(buffer, 0, buffer.Length);
fs.Flush();
fs.Close();
}
rdr.Close();
txn.Commit();
con.Close();
}
}
Here's a method that can be used to read bytes from one Stream to another Stream without regard for what type of Stream they each are.
Public Sub CopyStream(source As Stream, destination As Stream, Optional blockSize As Integer = 1024)
Dim buffer(blockSize - 1) As Byte
'Read the first block.'
Dim bytesRead = source.Read(buffer, 0, blockSize)
Do Until bytesRead = 0
'Write the current block.'
destination.Write(buffer, 0, bytesRead)
'Read the next block.'
bytesRead = source.Read(buffer, 0, blockSize)
Loop
End Sub
I am working on a Self Hosted WPF Application (using Owin) that returns bitmap images to the browser.
My controller code looks like this:
public ImageSource GetmbTiles(string FILE, string Z, string X, string Y)
{
string mbtiles = string.Format(("C:\\{0}.mbtiles"), FILE);
string connString = string.Format("Data Source={0}", mbtiles);
using (SQLiteConnection conn = new SQLiteConnection(connString))
{
System.Text.StringBuilder Query = new System.Text.StringBuilder();
Query.Append("SELECT tile_data ");
Query.Append("FROM tiles ");
Query.Append(string.Format("where zoom_level={0} and tile_column={1} and tile_row={2} ", Z, X, Y));
using (SQLiteCommand cmd = new SQLiteCommand(Query.ToString(), conn))
{
conn.Open();
using (SQLiteDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
buffer = GetBytes(dr);
}
}
}
}
//return new System.IO.MemoryStream(buffer);
return byteArrayToImage(buffer);
}
private static BitmapImage byteArrayToImage(byte[] imageData)
{
if (imageData == null || imageData.Length == 0) return null;
var image = new BitmapImage();
using (var mem = new MemoryStream(imageData))
{
mem.Position = 0;
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = null;
image.StreamSource = mem;
image.EndInit();
}
image.Freeze();
return image;
}
private static byte[] GetBytes(SQLiteDataReader reader)
{
const int CHUNK_SIZE = 2 * 1024;
byte[] buffer = new byte[CHUNK_SIZE];
long bytesRead = 0;
long fieldOffset = 0;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
bytesRead = reader.GetBytes(0, fieldOffset, buffer, 0, buffer.Length);
while (bytesRead == buffer.Length)
{
stream.Write(buffer, 0, Convert.ToInt32(bytesRead));
fieldOffset += bytesRead;
bytesRead = reader.GetBytes(0, fieldOffset, buffer, 0, buffer.Length);
}
stream.Write(buffer, 0, Convert.ToInt32(bytesRead));
return stream.ToArray();
}
}
When I call this controller from my browser I only get a json file and not the image.
The exception Message is
<ExceptionMessage>Type 'System.IO.MemoryStream' with data contract name 'MemoryStream:http://schemas.datacontract.org/2004/07/System.IO' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.</ExceptionMessage>
I am web developer very new to the world of WPF so pardon this noob question. But whatever I try to return the image so far isnt helping. I can see that the byte array is being populated. But the Byte Array wont display in a browser, is there some conversion that I am missing ? Any hint or help will be highly appreciated.
I am posting this solution for anyone else who may be in the same scenario, OWIN Self Hosted App that serves images or other files.
I resolved this by adding this to the controller method
Image img = byteArrayToImage(buffer);
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(ms.ToArray());
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
return result;
public Image byteArrayToImage(byte[] byteArrayIn)
{
MemoryStream ms = new MemoryStream(byteArrayIn);
Image returnImage = Image.FromStream(ms);
return returnImage;
}
Someone on here already pushed me in the right direction. I believe I am on the correct track now to pull all of my blobs out of my database. The only thing I cannot figure out is (I think) is where to set where it saves to.
Here is all the code:
namespace PullBlobs
{
class Program
{
static void Main()
{
string connectionString = "Data Source=NYOPSSQL05;Initial Catalog=Opsprod;Integrated Security=true;User Id=username;Password=password;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "Select FileName, FileData from IntegrationFile where IntegrationFileID = #Request_ID";
cmd.Connection = connection;
cmd.Parameters.Add("#Request_ID", SqlDbType.UniqueIdentifier).Value = new Guid("EBFF2CEA-3FF9-4D22-ABEF-3240647119CC");
connection.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
{
// Writes the BLOB to a file (*.bmp).
FileStream stream;
// Streams the BLOB to the FileStream object.
BinaryWriter writer;
// Size of the BLOB buffer.
int bufferSize = 100;
// The BLOB byte[] buffer to be filled by GetBytes.
byte[] outByte = new byte[bufferSize];
// The bytes returned from GetBytes.
long retval;
// The starting position in the BLOB output.
long startIndex = 0;
// The publisher id to use in the file name.
string FileName = "";
// Get the publisher id, which must occur before getting the logo.
FileName = reader.GetString(0);
// Create a file to hold the output.
stream = new FileStream(
FileName + ".txt", FileMode.OpenOrCreate, FileAccess.Write);
writer = new BinaryWriter(stream);
// Reset the starting byte for the new BLOB.
startIndex = 0;
// Read bytes into outByte[] and retain the number of bytes returned.
retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
// Continue while there are bytes beyond the size of the buffer.
while (retval == bufferSize)
{
writer.Write(outByte);
writer.Flush();
// Reposition start index to end of last buffer and fill buffer.
startIndex += bufferSize;
retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);
}
// Write the remaining buffer.
writer.Write(outByte, 0, (int)retval - 1);
writer.Flush();
// Close the output file.
writer.Close();
stream.Close();
}
// Close the reader and the connection.
reader.Close();
connection.Close();
}
}
}
}
I think I have every thing altered the way I need it except for where to set the path to save the files to. Here is the link I found on msdn where I pulled most of this code (and altered it) from.
https://msdn.microsoft.com/en-us/library/87z0hy49(v=vs.110).aspx
Dumb question, but are there any actual blobs in there for that request id?
Furthermore, Since you are just reading blobs from the database and writing them to files, why not use BCP?
https://msdn.microsoft.com/en-us/library/ms162802.aspx
I figured out the answer of where to put the path. Make sure you put the # symbol before the quotation marks.
stream = new FileStream(#"c:\dev\Blobs\" + FileName + ".txt", FileMode.OpenOrCreate, FileAccess.Write);
I have a following problem:
I am using c# and .aspx pages. On .aspx page i have a GridView. I set a GridView datasource to be:
GridView1.DataSource = PictureInfo.PictureInfoList;
My "PictureInfo" class looks like this:
public class PictureInfo
{
public static List<PictureInfo> PictureInfoList = new List<PictureInfo>();
public string PictureDescription { get; set; }
public byte[] Picture { get; set; }
}
Is it possible and how to show a picture which is in "byte[] Picture" in a GridView? Or which way it is possible? I'm saving data in this way before i send it to a database. And i would like to show it in a GridView before i send it to a database. As you can see I'm a beginner but i would be very happy if i could make this work. My head hearts already from reading some solutions online, none helped until now.
thank you very much
I suggest you a solution for: Converting byte[] to Bitmap (may it will be useful for you):
public BitmapSource ByteArrayToBitmap(byte[] byteArray) {
BitmapSource res;
try {
using (var stream = new MemoryStream(byteArray)) {
using (var bmp = new Bitmap(stream)) {
res = ToBitmap(bmp);
}
}
} catch {
res = null;
}
return res;
}
public BitmapSource ToBitmap(Bitmap bitmap) {
using (var stream = new MemoryStream()) {
bitmap.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
var result = new BitmapImage();
result.BeginInit();
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
Next, you should adapt, and include the Bitmap in your GridView.
on your handler.ashx
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpeg";
string ImageID=request["ID"];
//byte[] ImageByte=pictureInfo.Picture;//local imageByte
byte[] ImageByte=getImage(ImageId);//image byte from any other sour,e.g database
Stream strm = new MemoryStream(ImageByte));
long length = strm.Length;
byte[] buffer = new byte[length];
int byteSeq = strm.Read(buffer, 0, 2048);
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, 2048);
}
}
now set image url for your asp:image inside your gridview as follows
Image1.ImageUrl = "somthing.ashx?ID="+userImageID;
i hope you have unique id for your image to be visible. I hope you have all set now. Comments and query are well comed.
retrieve image byte from database
public byte[] GetImage(string ImageId)
{ byte[] img = null;
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "SlikaHendler";
cmd.Parameters.AddWithValue("#Id", ImageId);
cmd.Connection = yourConnection();
SqlDataReader dr = null;
dr = cmd.ExecuteReader();
if (dr.Read())
{
img = (byte[])dr[0];
}
dr.Close();
return img;//returns array of byte
}
I know pictures are recorded as binaries to databases. In this aspect, your problem turns to a "converting binary to byte".
If you can reach your picture info as binary data, you can convert it as taking 3 digits for 1 byte, and convert & show as bytes.
http://en.wikipedia.org/wiki/ASCII
I have a code to stream a snapshot from an IP camera and save it on harddisk.
Then I have another code to read it and store it in ms-sql database.
I know that it will be more faster if I just stream the image and save it in the database without saving it on the harddisk and read it again. But I don't know how to merge this.
Code to get the image
string sourceURL = "http://" + ip + "/cgi-bin/cmd/encoder?SNAPSHOT";
WebRequest req = (WebRequest)WebRequest.Create(sourceURL);
req.Credentials = new NetworkCredential("admin", "123456");
WebResponse resp = req.GetResponse();
Stream stream = resp.GetResponseStream();
Bitmap bmp = (Bitmap)Bitmap.FromStream(stream);
bmp.Save(ImagePath);
Then to insert the image to the database:
byte[] imageData = ReadFile(ImageName);
using (SqlConnection cn = new SqlConnection(constr))
{
string qry = "update vaiolations set val_image=#ImageData ,valid=1 where id=#OriginalPath ";
SqlCommand SqlCom = new SqlCommand(qry, cn);
SqlCom.Parameters.Add(new SqlParameter("#OriginalPath", (object)id));
SqlCom.Parameters.Add(new SqlParameter("#ImageData", (object)imageData));
cn.Open();
SqlCom.ExecuteNonQuery();
cn.Close();
cn.Dispose();
}
byte[] ReadFile(string sPath)
{
using (FileStream fStream = new FileStream(sPath, FileMode.Open, FileAccess.Read))
{
byte[] data = null;
FileInfo fInfo = new FileInfo(sPath);
long numBytes = fInfo.Length;
BinaryReader br = new BinaryReader(fStream);
data = br.ReadBytes((int)numBytes);
return data;
}
}
How can I combine these two code snippets to stream the image and then immediately insert it into the database?
Why are you converting the incoming bytes to a Bitmap?
You could probably just read the stream to a memory stream, and pass it on to the database:
Stream stream = resp.GetResponseStream();
byte[] data;
using (MemoryStream ms = new MemoryStream())
{
int num_bytes = 0;
byte[] temp = new byte[4096];
while ((num_bytes = stream.Read(temp, 0, temp.Length)) > 0)
ms.Write(temp, 0, bytes);
data = ms.ToArray();
}
Then pass data to your database.