Stream / MemoryStream
-
I cannot figure this out.. Basically I read the bytes from my database, saved it to he harddrive, then attached it to an email, then delete the file. So I wanted to put this in a stream or memorystream then attach it to an email so I skip all the file saving.
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
FileData = myReader["Saved_File"].ToString();
byte[] buffer = new byte[FileData.Length];
ms.Read(buffer, 0, FileData.Length);
mm.Attachments.Add(new Attachment(ms, myReader["Filename"].ToString()));
}It attaches, but only up to 77 bytes. I'm lost.. In my database it is stored as a varbinary(MAX). It works if I save it to the harddrive. I just want to skip all of that.
-
I cannot figure this out.. Basically I read the bytes from my database, saved it to he harddrive, then attached it to an email, then delete the file. So I wanted to put this in a stream or memorystream then attach it to an email so I skip all the file saving.
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
FileData = myReader["Saved_File"].ToString();
byte[] buffer = new byte[FileData.Length];
ms.Read(buffer, 0, FileData.Length);
mm.Attachments.Add(new Attachment(ms, myReader["Filename"].ToString()));
}It attaches, but only up to 77 bytes. I'm lost.. In my database it is stored as a varbinary(MAX). It works if I save it to the harddrive. I just want to skip all of that.
Jacob D Dixon wrote:
FileData = myReader["Saved_File"].ToString();
Is Saved_File the byte array or is for example the original name of the file? I would guess, that you have used it for both purposes because later you have:
Jacob D Dixon wrote:
byte[] buffer = new byte[FileData.Length];
Also your post doesn't show how the memory stream is constructed or what's the type of FileData so it's quite hard to say if they are correctly.
The need to optimize rises from a bad design.My articles[^]
-
Jacob D Dixon wrote:
FileData = myReader["Saved_File"].ToString();
Is Saved_File the byte array or is for example the original name of the file? I would guess, that you have used it for both purposes because later you have:
Jacob D Dixon wrote:
byte[] buffer = new byte[FileData.Length];
Also your post doesn't show how the memory stream is constructed or what's the type of FileData so it's quite hard to say if they are correctly.
The need to optimize rises from a bad design.My articles[^]
I'm sorry I have never done this before. What I have there is what I've tried to get to work from what I've seen on the internet. myReader["Saved_File"].ToString(); is reading the varbinary from the SQL database (Saved_File) column. So i'm taking the string FileData and storing the information in the SQL database in the string. So what I'm trying to do is take the data from the database and attach it in an email without actually saving a file to the harddrive then deleting it when I'm done. I'm wanting to store the file in memory, then attach it to the email and send it. Is this possible?
-
I cannot figure this out.. Basically I read the bytes from my database, saved it to he harddrive, then attached it to an email, then delete the file. So I wanted to put this in a stream or memorystream then attach it to an email so I skip all the file saving.
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
FileData = myReader["Saved_File"].ToString();
byte[] buffer = new byte[FileData.Length];
ms.Read(buffer, 0, FileData.Length);
mm.Attachments.Add(new Attachment(ms, myReader["Filename"].ToString()));
}It attaches, but only up to 77 bytes. I'm lost.. In my database it is stored as a varbinary(MAX). It works if I save it to the harddrive. I just want to skip all of that.
You have to loop on the read in order to get all of the data from the stream. The read method returns number of bytes read, loop until number of bytes read == number of bytes in file. Also, to string will only cause things to break. It is the most overused and misunderstood feature of .NET apparently.
Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
If you don't ask questions the answers won't stand in your way.
Most of this sig is for Google, not ego. -
I cannot figure this out.. Basically I read the bytes from my database, saved it to he harddrive, then attached it to an email, then delete the file. So I wanted to put this in a stream or memorystream then attach it to an email so I skip all the file saving.
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
FileData = myReader["Saved_File"].ToString();
byte[] buffer = new byte[FileData.Length];
ms.Read(buffer, 0, FileData.Length);
mm.Attachments.Add(new Attachment(ms, myReader["Filename"].ToString()));
}It attaches, but only up to 77 bytes. I'm lost.. In my database it is stored as a varbinary(MAX). It works if I save it to the harddrive. I just want to skip all of that.
Jacob D Dixon wrote:
FileData = myReader["Saved_File"].ToString();
You are getting the data as a byte array, but then you call the ToString method on the data. The Array class does not override the ToString method, so you are using the default implementation, which returns the name of the class. So, that line gives the same result as:
FileData = "System.Byte[]";
Jacob D Dixon wrote:
byte[] buffer = new byte[FileData.Length];
Here you are creating a new byte array with the size 13.
Jacob D Dixon wrote:
ms.Read(buffer, 0, FileData.Length);
Here you attemt to read the first 13 bytes from the memorystream. However, as you ignore the return value of the Read method, you don't know if you got one byte or 13 bytes. The Read method doesn't have to return the number of bytes that you requested, even if there are more bytes left in the stream, so you need to call Read in a loop until you have got all the data that you want, or until the method returns zero which means that it reached the end of the stream. However, I have no idea why you are trying to read the data from the memory stream into a byte array, when you are using the memory stream in the attachment. Also I don't know where you think that you get the data from the data reader into either the memory stream or the buffer...
Despite everything, the person most likely to be fooling you next is yourself.
-
Jacob D Dixon wrote:
FileData = myReader["Saved_File"].ToString();
You are getting the data as a byte array, but then you call the ToString method on the data. The Array class does not override the ToString method, so you are using the default implementation, which returns the name of the class. So, that line gives the same result as:
FileData = "System.Byte[]";
Jacob D Dixon wrote:
byte[] buffer = new byte[FileData.Length];
Here you are creating a new byte array with the size 13.
Jacob D Dixon wrote:
ms.Read(buffer, 0, FileData.Length);
Here you attemt to read the first 13 bytes from the memorystream. However, as you ignore the return value of the Read method, you don't know if you got one byte or 13 bytes. The Read method doesn't have to return the number of bytes that you requested, even if there are more bytes left in the stream, so you need to call Read in a loop until you have got all the data that you want, or until the method returns zero which means that it reached the end of the stream. However, I have no idea why you are trying to read the data from the memory stream into a byte array, when you are using the memory stream in the attachment. Also I don't know where you think that you get the data from the data reader into either the memory stream or the buffer...
Despite everything, the person most likely to be fooling you next is yourself.
Im not trying to read from a memorystream into a byte array. I'm trying to take the bytes from the database and put them into a Stream to attach to an email. Attachment of (System.Net.Mail) needs a file or a Stream
-
Jacob D Dixon wrote:
FileData = myReader["Saved_File"].ToString();
You are getting the data as a byte array, but then you call the ToString method on the data. The Array class does not override the ToString method, so you are using the default implementation, which returns the name of the class. So, that line gives the same result as:
FileData = "System.Byte[]";
Jacob D Dixon wrote:
byte[] buffer = new byte[FileData.Length];
Here you are creating a new byte array with the size 13.
Jacob D Dixon wrote:
ms.Read(buffer, 0, FileData.Length);
Here you attemt to read the first 13 bytes from the memorystream. However, as you ignore the return value of the Read method, you don't know if you got one byte or 13 bytes. The Read method doesn't have to return the number of bytes that you requested, even if there are more bytes left in the stream, so you need to call Read in a loop until you have got all the data that you want, or until the method returns zero which means that it reached the end of the stream. However, I have no idea why you are trying to read the data from the memory stream into a byte array, when you are using the memory stream in the attachment. Also I don't know where you think that you get the data from the data reader into either the memory stream or the buffer...
Despite everything, the person most likely to be fooling you next is yourself.
Figured it out. This is what I did:
...(SqlConnection, SqlCommand stuff up here)...
MailMessage mm = new MailMessage(...);
SqlDataReader myReader = null;conn.Open
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
object buffer = myReader["Saved_File"];
mm.Attachments.Add(new Attachment(new MemoryStream((byte[])buffer), myReader["Filename"].ToString()));
}conn.Close();
It works.. but is that a good way to do it. Basically tehre can be multiple files per ticket. So it goes through each file within the ticket (that has the ID of whatever) and puts it in the object buffer, then attaches it to an email. Is there a better way? I tested this and it works but I would love to learn a better or more correct way.
-
Figured it out. This is what I did:
...(SqlConnection, SqlCommand stuff up here)...
MailMessage mm = new MailMessage(...);
SqlDataReader myReader = null;conn.Open
myReader = cmd.ExecuteReader();
while (myReader.Read())
{
object buffer = myReader["Saved_File"];
mm.Attachments.Add(new Attachment(new MemoryStream((byte[])buffer), myReader["Filename"].ToString()));
}conn.Close();
It works.. but is that a good way to do it. Basically tehre can be multiple files per ticket. So it goes through each file within the ticket (that has the ID of whatever) and puts it in the object buffer, then attaches it to an email. Is there a better way? I tested this and it works but I would love to learn a better or more correct way.
I think that overall the solution is good. It's definitely better to process the data in memory rather than writing it to disk only to delete it right afterwards. Especially since the only reason for writing to disk was to use the file as an Attachment. Writing to disk is slower and more 'risky' than working with the data in memory. One small improvement would be to put a
try/catch/finally
around thewhile
loop and use thefinally
clause to close the database resources. Another would be to declarebuffer
as the correct type just one time outside the loop and use safe type conversion followed by testing it fornull
. Another thing to improve might be accessing the 'Filename' field without testing forDBNull
or anything; but that may not be an issue for your data (you might have the field declarednot null
in the database, or might be defaulting it to''
if it'snull
in your query, etc.).try
{
byte[] buffer = null; <----- declare it here as null and of type byte[]
while(myReader.Read())
{
buffer = myReader["Saved_File"] as byte[]; <----- safely convert the return value here
if(buffer == null) <----- conversion failed, skip this item
continue;
mm.Attachments.Add(new Attachment(new MemoryStream(buffer), myReader["Filename"].ToString()));
}
}
catch
{
//
}
finally <----- close out database resources here
{
if(myReader != null)
myReader.Close();
if(conn != null)
conn.Close();
}Keep It Simple Stupid! (KISS)