Reputation: 4740
I'm trying save a image in my D: directory, and to accomplish this, I'm save in Session
some informations from my FileUpload
component.
In my method called btnConfirm_Click
I create my Session
and in my btnSave_Click
method I recover this information and try to save the file, but when I check in my D:
directory, the file exist but when I open this file, I saw the message: The windows photo viewer can not open this picture because the file appears to be damaged, corrupted, or is too big ..
Someone can help me ?
C# Code
protected void btnConfirm_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
string sFileName = FileUpload1.FileName;
string fileExtension = System.IO.Path.GetExtension(sFileName).ToLower();
foreach (string ext in new string[] { ".jpeg", ".jpg", ".png" })
{
if (fileExtension == ext)
{
Session["Document"] = sFileName + fileExtension;
Session["Byte"] = FileUpload1.FileBytes;
Session["Content"] = FileUpload1.FileContent;
byte[] b = (byte[])Session["Byte"];
}
}
}
}
protected void btnSave_Click(object sender, EventArgs e)
{
if (Session["Document"].ToString() != null)
{
try
{
byte[] byteArray = Encoding.UTF8.GetBytes(Session["Content"].ToString());
MemoryStream stream = new MemoryStream(byteArray);
sPath = "D:/123.jpg";
FileStream fileStream = File.Create(sPath, (int)stream.Length);
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, bytesInStream.Length);
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
catch
{
}
}
}
Upvotes: 0
Views: 3367
Reputation: 4548
Try to wrap the FileStream
in using statement.
FileStream ref: http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx
Here is the reference to Streams in general: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx
Why you have to wrap this statement in a using statement? When you use managed resources in your code like files, connections to database or any other of this kind you have to specify manually when you want these resource to be freed from the managed heap (your RAM). Well, this is not 100% valid statement because this can happen automatically when the garbage collection kicks in and removes the all unused objects. There are some points you must know to understand what kind of code you should write.
1) The garbage collection kicks in only on memory pressure, not timer.
2) Every Managed resource is implemented by Inheriting SafeHandle class. http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx This abstract class has a method called Dispose()
which only job is to safely free any managed resources it created. The dispose method is invoked by the Garbage Collector or when you manually call it. For example, the using construction is a short cut to the following code:
var file;
try{ // code }
finally { file.Dispose(); }
PS: Most of the time you should avoid the using
statement and also calling Dispose()
. Why? Because you have GC, let it do his job. If you have problems that means you have to look carefully your code in general. Let the GC do what it does best. Finally, use using
or Dispose()
only, I mean it, only when you are sure no one else is using your managed resource (for example in another thread).
Upvotes: 0
Reputation: 131180
The message says that the file doens't contain image data. Your code never stores the file's content to disk.
What it does is to get the string representation of a Stream (FileUpload.FileContent) object (typically the name of the type) converts this name to a Unicode string, then tries to convert it back to binary as a UFT8 string and finally stores the results in a file.
The contents of Session["Content"]
is the original stream, so you can just copy the contents of one stream to the other using Stream.CopyTo, eg.
var sourceStream=(Stream)Session["Content"];
using(var fileStream=File.Create(targetPath,sourceStream.Length);
{
sourceStream.CopyTo(fileStream);
}
Even better, don't use Session at all. Unless something causes the FileUpload1 control to lose its contents, its content will still be available when you execute your btnSave_Click handler. In this case you can use FileUpload.Save to save the file directly to disk.
Besides, using Session is the wrong place to store file data. Session uses either the machine's memory or a database to store its data, which can result in poor performance when you store large data there. Sessions stay alive for a long time which means that the file data will remain in memory even after you no longer need it, unless you explicitly remove it.
Upvotes: 1
Reputation: 44696
byte[] byteArray = Encoding.UTF8.GetBytes(Session["Content"].ToString());
This line looks very wrong. You are taking a string (encoded as UTF8) and trying to turn it into a binary JPG image. This won't work. You need to keep the original image in binary (not textual + encoding) form. When you turn byte[]
into a string
(or vice-versa) there is an information loss because a textual encoding can't (in general) represent all byte sequence.
As @PanagiotisKanovas mentions, you want to be getting the Session['Content']
stream of data.
As an aside, you aren't closing your streams, so it's possible that when you try to open the file the object is still locked.
using (FileStream fileStream = File.Create(sPath, (int)stream.Length)) {
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, bytesInStream.Length);
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
Upvotes: 5