我似乎无法为我的真正问题得到答案Invalid parameter when retrieving image from DB所以Imma一块一块地尝试。 在C#和MS Access 2010中使用Visual Studio 2012.我的解决方案是一个非Web相关的应用程序。
我不确定这部分,所以我的问题是如何正确地从查询中获取行中的 OLE对象的图像一个字节数组( byte [] ),因为肯定不是我用以下代码做的。 我正在谈论的那一行是 row [“FOTO”] 。
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM [APP_Equipamento_Geral] WHERE COD_ETIQ like '%" + codigo + "%'", l);
DataSet ds = new DataSet();
adapter.Fill(ds, "[APP_Equipamento_Geral]");
string s = ds.Tables["[APP_Equipamento_Geral]"].Columns[16].ColumnName;
foreach (DataRow row in ds.Tables["[APP_Equipamento_Geral]"].Rows)
{
eq.NSerie = row["N_SERIE"].ToString();
eq.NInventario = row["Codigo"].ToString();
if (row["FOTO"] != DBNull.Value && row["FOTO"] != null)
{
string str = row["FOTO"].ToString();
byte[] b = stringToByteArray(str);
byte[] imagebyte = GetImageBytesFromOLEField(b); //Error caught here
MemoryStream ms = new MemoryStream();
ms.Write(imagebyte, 0, imagebyte.Length);
}
}
可以找到方法GetImageBytesFromOLEField here。它给我的错误是关于字符串的索引长度strVTemp = strTemp.Substring(0,300);
同样,这里的主要问题是如何将 DataRow行[“FOTO”] 中的 OLE Object 转换为 byte [] 然后用在那个方法中。
答案 0 :(得分:3)
这里的问题是嵌入的图片不是简单的BMP
或JPEG
。这是一个
Microsoft Word Picture
并且OLE头信息比原始GetImageBytesFromOLEField()
代码的300字节窗口大得多。 (也就是说,在扫描300个字节后,它只是放弃了“无法确定标题大小......”。)
以下是该类代码的更新版本。粗略测试包括提供的Microsoft Word Picture
,简单的BMP
和简单的JPEG
。
using System;
using System.Collections.Generic;
using System.Linq;
namespace OleImageTest
{
public static class OleImageUnwrap
{
public static byte[] GetImageBytesFromOLEField(byte[] oleFieldBytes)
{
// adapted from http://blogs.msdn.com/b/pranab/archive/2008/07/15/removing-ole-header-from-images-stored-in-ms-access-db-as-ole-object.aspx
const int maxNumberOfBytesToSearch = 10000;
byte[] imageBytes; // return value
var imageSignatures = new List<byte[]>();
// PNG_ID_BLOCK = "\x89PNG\r\n\x1a\n"
imageSignatures.Add(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A });
// JPG_ID_BLOCK = "\xFF\xD8\xFF"
imageSignatures.Add(new byte[] { 0xFF, 0xD8, 0xFF });
// GIF_ID_BLOCK = "GIF8"
imageSignatures.Add(new byte[] { 0x47, 0x49, 0x46, 0x38 });
// TIFF_ID_BLOCK = "II*\x00"
imageSignatures.Add(new byte[] { 0x49, 0x49, 0x2A, 0x00 });
// BITMAP_ID_BLOCK = "BM"
imageSignatures.Add(new byte[] { 0x42, 0x4D });
int numberOfBytesToSearch = (oleFieldBytes.Count() < maxNumberOfBytesToSearch ? oleFieldBytes.Count() : maxNumberOfBytesToSearch);
var startingBytes = new byte[numberOfBytesToSearch];
Array.Copy(oleFieldBytes, startingBytes, numberOfBytesToSearch);
var positions = new List<int>();
foreach (byte[] blockSignature in imageSignatures)
{
positions = startingBytes.IndexOfSequence(blockSignature, 0);
if (positions.Count > 0)
{
break;
}
}
int iPos = -1;
if (positions.Count > 0)
{
iPos = positions[0];
}
if (iPos == -1)
throw new Exception("Unable to determine header size for the OLE Object");
imageBytes = new byte[oleFieldBytes.LongLength - iPos];
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ms.Write(oleFieldBytes, iPos, oleFieldBytes.Length - iPos);
imageBytes = ms.ToArray();
ms.Close();
ms.Dispose();
return imageBytes;
}
private static List<int> IndexOfSequence(this byte[] buffer, byte[] pattern, int startIndex)
{
// ref: http://stackoverflow.com/a/332667/2144390
List<int> positions = new List<int>();
int i = Array.IndexOf<byte>(buffer, pattern[0], startIndex);
while (i >= 0 && i <= buffer.Length - pattern.Length)
{
byte[] segment = new byte[pattern.Length];
Buffer.BlockCopy(buffer, i, segment, 0, pattern.Length);
if (segment.SequenceEqual<byte>(pattern))
positions.Add(i);
i = Array.IndexOf<byte>(buffer, pattern[0], i + 1);
}
return positions;
}
}
}