由Stream.Position问题而引发的思考
{
List<ImageEntity> images = new List<ImageEntity>();
HttpFileCollection files = Request.Files;
int fileLen;
ImageEntity image = null;
if (files != null && files.Count > 0)
{
for (int i = 0; i < files.Count; i++)
{
if (files[i].FileName.Length != 0)
{
try
{
fileLen = files[i].ContentLength;
Byte[] bytes = new Byte[fileLen];
stream.Read(bytes, 0, fileLen);
image = new ImageEntity();
image.Type = files[i].ContentType;
image.ImageBlob = bytes;
image.Title = Path.GetFileName(files[i].FileName);
images.Add(image);
}
catch { }
}
}
}
return images;
}
{
public ImageEntity()
{
}
public ImageEntity(string title, Byte[] imageBlob, string type)
{
Title = title;
ImageBlob = imageBlob;
Type = type;
}
public string Title { get; set; }
public string Type { get; set; }
public Byte[] ImageBlob { get; set; }
}
这么使用是没有问题的!当我们上传图片时,页面通过Post方法提交到服务端,服务端构造一个和图片字节大小相同的byte数组,通过HttpPostedFile的InputStream属性得到一个System.IO.Stream对象,然后使用该对象的Read方法将图片数据流读到byte数组中。这个过程页面是需要回传的,并且下一次用户上传图片时Stream对象会被重新构造,然后重新填充byte数组。
不过在一次MOSS开发中我偶然地发现使用该方式上传图片时,保存图片到数据库没有出现问题,当从数据库中读取图片时却显示了一个红色的叉,表示图片不可用或加载失败。仔细查看了一下数据库中的数据,除了保存图片二进制数据的字段显示为<Binary data>外,其余字段的数据都很正常,没有发现什么异常情况,调试了一下程序,图片上传和保存的过程中并没有抛出任何异常,一切都很顺利,但就是在读取图片的时候页面上无法正常加载图片。
一开始我就感觉这个问题很奇怪,看来问题应该是出在上传图片时图片的二进制数据获取得不正确或不完整,我再次调试跟踪了一下代码,发现在上传的过程中byte数组中的值始终都是0,即便是在通过Stream.Read方法填充数据之后也是如此。这到底是为什么?难道我用错对象了?查了一下MSDN,发现上面给出的示例基本上也是通过这种方法得到要上传的文件并通过Stream.Read方法填充byte数组的,MSDN的示例代码肯定是不会有错误的,那错误到底在哪里呢?我开始迷惑了...
仔细搜了搜Google,其中有一位朋友给出的帮助对我很有用,他建议在使用Stream.Read方法填充byte数组前先判断一下Stream.Position的值是否为0,如果不为0就先将它置为0,然后再进行byte数组的填充。不过我先是想到每次页面在上传文件时所构造的Stream对象都是新的(因为页面会PostBack回来),我并没有在程序的任何地方缓存Stream对象,既然Stream对象是新的,那么Position属性的值肯定就是0啦。我抱着半信半疑的心态试了试这位朋友介绍的方法,果然奏效了,看来Stream对象真的是在某个地方被缓存了,或者说在前一次文件上传之后Stream对象没有被完全释放。于是我修改了上面的那个得到上传图片的方法。
{
List<ImageEntity> images = new List<ImageEntity>();
HttpFileCollection files = Request.Files;
int fileLen;
ImageEntity image = null;
if (files != null && files.Count > 0)
{
for (int i = 0; i < files.Count; i++)
{
if (files[i].FileName.Length != 0)
{
try
{
fileLen = files[i].ContentLength;
Byte[] bytes = new Byte[fileLen];
using (Stream stream = files[i].InputStream)
{
stream.Position = 0;
stream.Read(bytes, 0, fileLen);
}
image = new ImageEntity();
image.Type = files[i].ContentType;
image.ImageBlob = bytes;
image.Title = Path.GetFileName(files[i].FileName);
images.Add(image);
}
catch { }
}
}
}
return images;
}