2013-07-11 2 views
0

Я пытаюсь сохранить изображение в моей директории D:, и для этого я сохраняю Session некоторые данные из моего FileUpload компонента.Файл сохраняется через Stream, но не может быть открыт

В моем методе называется btnConfirm_Click Я создаю мой Session и в моем btnSave_Click методы я восстановить эту информацию и попытаться сохранить файл, но когда я проверяю в моем D: каталоге, файл существует, но когда я открываю этот файл, я увидел сообщение: The windows photo viewer can not open this picture because the file appears to be damaged, corrupted, or is too big ..

Кто-то может мне помочь?

C# Код

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 
        { 
        } 
       } 
     } 

ответ

5
byte[] byteArray = Encoding.UTF8.GetBytes(Session["Content"].ToString()); 

Эта линия выглядит очень неправильно. Вы берете строку (закодированную как UTF8) и пытаетесь превратить ее в двоичный JPG-образ. Это не сработает. Вы должны сохранить исходное изображение в двоичной (не текстовой + кодировке) форме. Когда вы поворачиваете byte[] в string (или наоборот), есть потеря информации, потому что текстовое кодирование не может (в общем) представлять всю последовательность байтов.

Как @PanagiotisKanovas упоминает, вы хотите получить поток данных Session['Content'].

Как в стороне, вы не закрываете свои потоки, поэтому возможно, что при попытке открыть файл объект все еще заблокирован.

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); 
} 
+2

И сеанс [«Содержимое»] - это поток, а не массив байтов –

+0

@JeffFoster Спасибо! Оно работает. –

0

Try обернуть FileStream в использовании заявление.

FileStream исх: http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx

Вот ссылка на Streams в целом: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx

Почему вы должны обернуть это заявление в использовании заявление? Когда вы используете управляемые ресурсы в своем коде, например файлы, подключения к базе данных или любые другие подобные вам, вам нужно указать вручную, когда вы хотите, чтобы этот ресурс был освобожден из управляемой кучи (вашей ОЗУ). Ну, это не 100% действительный оператор, потому что это может произойти автоматически, когда сбор мусора срабатывает и удаляет все неиспользуемые объекты. Есть некоторые моменты, которые вы должны знать, чтобы понять, какой код вы должны писать.

1) Сбор мусора запускается только по памяти, а не по таймеру.
2) Каждый управляемый ресурс реализуется путем наследования класса SafeHandle. http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx Этот абстрактный класс имеет метод под названием Dispose(), который только для работы - это безопасное освобождение любых созданных ими управляемых ресурсов. Метод dispose вызывается сборщиком мусора или когда вы его вручную вызываете. Например, использование конструкции является кратчайшая на следующий код:

var file; 
try{ // code } 
finally { file.Dispose(); } 

PS: Большая часть времени вы должны избегать using заявления, а также вызова Dispose(). Зачем? Потому что у вас есть GC, пусть он выполняет свою работу. Если у вас есть проблемы, это означает, что вам нужно внимательно изучить свой код в целом. Пусть GC сделает то, что он делает лучше всего. Наконец, используйте только using или Dispose(), я имею в виду, только если вы уверены, что никто другой не использует ваш управляемый ресурс (например, в другом потоке).

+0

* Почему? * (На самом деле я знаю ответ, но OP, вероятно, не понимает или даже не знает шаблон 'IDisposable') –

+0

Вот почему я перенаправляю его на страницу FileStream в MSDN. – mynkow

+0

Нет ничего полезного для понимания одноразового шаблона на этой странице. Доступен только необходимый метод (Dispose). Тот факт, что Stream реализует IDisposable, даже не указан. –

1

В сообщении говорится, что файл не содержит данных изображения. Ваш код никогда не сохраняет содержимое файла на диск.

Что нужно сделать, чтобы получить строковое представление объекта Stream (FileUpload.FileContent) (обычно это имя типа) преобразует это имя в строку Unicode, а затем пытается преобразовать его обратно в двоичный как строку UFT8 и, наконец, сохраняет результаты в файле.

Содержимое Session["Content"] является исходным потоком, поэтому вы можете просто скопировать содержимое одного потока в другой, используя Stream.CopyTo, например.

var sourceStream=(Stream)Session["Content"]; 
using(var fileStream=File.Create(targetPath,sourceStream.Length); 
{ 
    sourceStream.CopyTo(fileStream); 
} 

Еще лучше, не используйте сессию вообще. Если что-то не приведет к тому, что элемент управления FileUpload1 потеряет свое содержимое, его содержимое будет доступно при выполнении вашего обработчика btnSave_Click. В этом случае вы можете использовать FileUpload.Save, чтобы сохранить файл непосредственно на диск.

Кроме того, использование Сессии - это неправильное место для хранения данных файла. Сеанс использует либо память устройства, либо базу данных для хранения своих данных, что может привести к низкой производительности при хранении больших данных. Сеансы остаются в живых в течение длительного времени, а это значит, что данные файла останутся в памяти даже после того, как вы больше не нуждаетесь в нем, если вы явно не удалите его.

+0

Спасибо! Оно работает. –

Смежные вопросы