"Parameter is not valid" 使用 Image.fromStream 方法时

"Parameter is not valid" when using Image.fromStream method

我现在为这个问题苦苦挣扎了几个小时。

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.Drawing.dll 中发生了 'System.ArgumentException' 类型的未处理异常 附加信息:参数无效。"

我已经尝试了几个我找到的代码示例,结果总是这个。有人知道这里有什么问题吗?

图片在上传到数据库时可能没有正确保存,或者您在将其转换回时可能会遇到问题。

我要做的一件事是声明你的字节数组的类型 SQL:

params.Add(New SqlParameter("@Image", bArr, SqlDbType.VarBinary,-1))

将图像加载到数据库时,您并未将数据用作图像类型。使用 File.ReadAllBytes:

获取二进制数据会更容易
Dim bArr As Byte()
bArr = File.ReadAllBytes(path)

此外,您可以通过尝试将数据保存到磁盘而不是加载到图片框来测试以确认从数据库保存的数据看起来正确。如果您无法将其作为图像打开,则保存的数据有问题:

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

最后,return 代码再次出现范围问题,您的 x Image 变量可能会在 space 之间的短短两行中被收集范围以及分配给 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