"Параметр недействителен" при использовании метода Image.fromStream
Я часами борюсь с этой проблемой.
If result = Windows.Forms.DialogResult.OK Then
Dim path As String = OpenFileDialog1.FileName
Dim img As Image = Image.FromFile(path)
Using mStream As New MemoryStream()
img.Save(mStream, img.RawFormat)
Dim bArr As Byte() = mStream.ToArray()
End Using
Dim params As New List(Of SqlParameter)
params.Add(New SqlParameter("@Image", bArr))
CallSP("UpdateImageSP", params)
End If
Это фактически обновит базу данных в столбце varbinary со значением: 0x89504E470D0A1A0A0000000D49484452000004120000041208060000001258D9C6000000017352474200AECE1CE900000004
Время извлечь изображение и показать его в картинке:
Dim dtIcon As DataTable = DataTableGet("getImageSP")
If dtIcon IsNot Nothing AndAlso Not dtIcon.Rows(0)("Image") Is DBNull.Value Then
Dim imageData As Byte() = DirectCast(dtIcon.Rows(0)("Image"), Byte())
If imageData.Length > 0 Then
Using mStream As New MemoryStream(imageData)
Dim x As Image = Image.FromStream(mStream) --<--ERROR HERE !!
End Using
PictureBox1.BackgroundImage = x
End If
End If
Ошибка "Произошло необработанное исключение типа" System.ArgumentException "в System.Drawing.dll. Дополнительная информация: параметр недействителен".
Я пробовал несколько примеров кода, которые я нашел, результат всегда был таким. Кто-нибудь знает, в чем здесь проблема?
2 ответа
Изображение может быть неправильно сохранено при загрузке в базу данных, или у вас могут возникнуть проблемы с его преобразованием.
Одна вещь, которую я хотел бы сделать, это объявить тип вашего байтового массива, идущего в SQL:
params.Add(New SqlParameter("@Image", bArr, SqlDbType.VarBinary,-1))
При загрузке изображения в базу данных вы не используете данные в качестве типа изображения. Было бы проще получить двоичные данные, используя File.ReadAllBytes:
Dim bArr As Byte()
bArr = File.ReadAllBytes(path)
Кроме того, вы можете проверить, чтобы убедиться, что сохраненные данные из базы данных выглядят правильно, попытавшись сохранить их на диск, а не загружать в Picturebox. Если вы не можете открыть его как изображение, значит что-то не так с сохраненными данными:
Dim stream As New FileStream([Some Test Path], FileMode.Create, FileAccess.Write)
stream.Write(imageData, 0, imageData.Length)
stream.Close()
Ваш первый фрагмент кода не должен работать. Есть ошибка, потому что этот код создает блок области видимости:
Using mStream As New MemoryStream()
img.Save(mStream, img.RawFormat)
Dim bArr As Byte() = mStream.ToArray()
End Using
Как только этот блок закрыт, bArr
Массив выходит из области видимости (примечание: не удаляется. Просто выходит из области видимости) при последующем его использовании:
params.Add(New SqlParameter("@Image", bArr))
Чтобы исправить это, либо расширьте блок области действия, либо объявите bArr
перед блоком области:
If result = Windows.Forms.DialogResult.OK Then
Dim path As String = OpenFileDialog1.FileName
Dim img As Image = Image.FromFile(path)
Dim bArr() As Byte
Using mStream As New MemoryStream()
img.Save(mStream, img.RawFormat)
bArr = mStream.ToArray()
End Using
Dim params As New List(Of SqlParameter)
params.Add(New SqlParameter("@Image", bArr))
CallSP("UpdateImageSP", params)
End If
То, что это пока работает для вас, является случайностью того, что сбор мусора произошел не в то время. Я не знаю, что это решит вашу проблему, но вы все равно должны решить ее.
Чтобы более тщательно проверить проблему по вашему вопросу, я бы временно изменил метод сохранения вашего байта при загрузке в БД, чтобы вы могли сравнивать его байт с байтом с массивом при извлечении его из БД. Найдите и проанализируйте любые различия. Если они одинаковые (это то, на что вы надеетесь), пришло время перейти к следующему шагу.
Если бы мне пришлось угадывать, я бы сказал, что проблема заключается в использовании img.RawFormat
когда вы сохраняете его в потоке памяти, это как-то не тот формат, который вы ожидаете. В любом случае вы можете обойти эту проблему, загрузив байтовый массив непосредственно из файла:
If result = Windows.Forms.DialogResult.OK Then
Dim bArr As Byte() = IO.File.ReadAllBytes(OpenFileDialog1.FileName)
Dim params As New List(Of SqlParameter)
params.Add(New SqlParameter("@Image", bArr))
CallSP("UpdateImageSP", params)
End If
Наконец, код возврата снова имеет проблему области, где ваш x
Переменная изображения потенциально может быть собрана в том коротком двухстрочном интервале между тем, когда она выходит из области видимости и когда вы назначаете PictureBox:
Dim dtIcon As DataTable = DataTableGet("getImageSP")
If dtIcon IsNot Nothing AndAlso Not (dtIcon.Rows(0)("Image") Is DBNull.Value) Then
Dim imageData As Byte() = DirectCast(dtIcon.Rows(0)("Image"), Byte())
If imageData.Length > 0 Then
Using mStream As New MemoryStream(imageData)
PictureBox1.BackgroundImage = Image.FromStream(mStream)
End Using
End If
End If