经常有人问这个问题,如何取出northwind中employees表中的photo字段的图片并显示出来?
此表中图片显示常见的问题是:由于northwind数据库內含的 image 资料最开头有78 bytes 的表头,所以需要手动将它去除。这也是大多数人费劲心思都无法显示那九个员的的图片的原因。
下面我将首先使用windows forms取出图片,并显示出来,然后再使用asp.net+xml技术将整个表的数据在网站中显示出来。
一、使用winform
首先建立一个winform工程,并添加:
….
using system.data;
using system.io;
using system.data.sqlclient;
在窗体中添加一个按钮,比如button1,双击它,在事件中加入如下代码:
//这里只取id=2的员工图片,你可以根据需要修改自己的代码
byte[] imgbytearray = getimage(“2”);
if(imgbyte == null) return;
if(imgbytearray.length <= 78) return;
memorystream stream = new memorystream();
int32 offset = 78;//去除78字节的表头
stream.write(imgbytearray, offset, imgbytearray.length – offset);
//显示图片
image m_bitmap = image.fromstream(stream);
this.creategraphics().drawimage(m_bitmap, 0, 0);
stream.close();
上面getimage(…)是用来从数据库中取出图片的字节数组用的,代码如下:
private byte[] getimage(string employeeid)
{
string connstring;
//数据库连接字符串,根据你的需要修改
connstring = “server=.;database=northwind;uid=aspnet;pwd=aspnet;”;
using (sqlconnection conn = new sqlconnection(connstring))
{
string sqlselect = “select photo from employees where employeeid = ” + employeeid;
sqlcommand cmd = conn.createcommand();
cmd.commandtext = sqlselect;
conn.open();
using (sqldatareader dr = cmd.executereader(commandbehavior.singlerow))
{
if(dr.read())
{
if(dr[0] != null)
{
byte[] byteimg = (byte[])dr[0];
return byteimg;
}
}
}
}
return null;
}
编译运行,你就可以看到相应的图片了。怎么样?是不是感觉图片好象效果不太好,很粗糙的感觉。没关系,continue….
注:如果进行批量查询,以上代码还可以进行优化,
二、使用webform
由于本例采用的是sqlxml技术,因此,如需运行本例,你需要下载sqlxml3.0版本,它完全支持xml-xslt转换。(当然,你也可以采用我们经常使用的sql server读取显示技术来完成本例)
安装后之后往下继续…..
新建一个webform网站工程,
首先,添加microsoft.data.sqlxml.dll引用;
然后,添加如下命名空间:
using system.data.sqlclient;
using system.text;
using system.xml;
using system.xml.xpath;
using system.xml.xsl;
using microsoft.data.sqlxml;
using system.io;
在page_load外添加string northwindconnstring;
在page_load中间代码区添加:
private void page_load(object sender, system.eventargs e)
{
northwindconnstring = system.configuration.configurationsettings.appsettings[ “northwindconnstring” ]; //从web.config中读取数据库连接信息(下面称此句为“数据库连接语句”)
using (sqlconnection conn = new sqlconnection(connstring))
{
string sqlselect;
sqlselect = “select * from employees for xml auto, elements”;
sqlxmlcommand sqlxmlcommand = new sqlxmlcommand(northwindconnstring);
sqlxmlcommand.commandtext = sqlselect;
sqlxmlcommand.clientsidexml = true;
sqlxmlcommand.xslpath = server.mappath(“employeetransform.xslt”);
sqlxmlcommand.roottag = “newdataset”;
sqlxmlcommand.executetostream(response.outputstream);
response.end();
}
}
备注:上面的数据库连接信息是在web.config中配置的,相关配置如下:
<appsettings>
<add key=”northwindconnstring” value=”provider=sqloledb;server=(local);database=northwind;user id=aspnet;password=aspnet”/>
</appsettings>
如果你的配置信息不使用web.config配置文件,则在上面“数据库连接语句”处改为:
northwindconnstring = “provider=sqloledb;server=(local);database=northwind;user id=aspnet;password=aspnet”即可。
上面的代码使用了xml+xpath的转换技术,其中:
employeetransform.xslt的内容是(你需要将此文件加入到你的网站工程中):
<?xml version=”1.0″ encoding=”gb2312″?>
<xsl:stylesheet version=1.0 xmlns:xsl=”http://www.w3.org/1999/xsl/transform”
xmlns:msxsl=”urn:schemas-microsoft-com:xslt”
xmlns:vcsharp=”urn:vcsharp-com”
xmlns:ms=”urn:schemas-microsoft-com:xslt”>
<xsl:output method=”html” indent=”yes” doctype-public=”-//w3c//dtd html 3.2 final//en”/>
<xsl:template match=”newdataset”>
<html>
<head>
<title>
</title>
</head>
<body>
<table style=”border-collapse: collapse;font-size:9pt;” bordercolor=”#000000″ cellspacing=”0″ cellpadding=”6″ rules=”all” align=”center” border=”1″ frame=”box”>
<tr style=”text-align:center;font-weight:bold;background-color:#336699;color:#ffffff;”>
<td>employeeid</td>
<td>name</td>
<td>title</td>
<td>titleofcourtesy</td>
<td>birthdate</td>
<td>hiredate</td>
<td>address</td>
<td>city</td>
<td>region</td>
<td>postalcode</td>
<td>country</td>
<td>homephone</td>
<td>extension</td>
<td>photo</td>
<td>notes</td>
<td>photopath</td>
</tr>
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match=”employees”>
<tr style=”background-color:#99ccee;color:#000000;”>
<td><xsl:value-of select=”employeeid”/>
<xsl:variable name=”employeeid” select=”employeeid”/>
</td>
<td><xsl:value-of select=”lastname”/><xsl:text disable-output-escaping=”yes”>&nbsp;</xsl:text><xsl:value-of select=”firstname”/></td>
<td><xsl:value-of select=”title”/></td>
<td><xsl:value-of select=”titleofcourtesy”/></td>
<xsl:value-of select=”ms:format-date(birthdate, mmm dd, yyyy)”/></td>
<td><xsl:value-of select=”ms:format-date(hiredate, mmm dd, yyyy)”/>
</td>
<td><xsl:value-of select=”address”/></td>
<td><xsl:value-of select=”city”/></td>
<td><xsl:value-of select=”region”/></td>
<td><xsl:value-of select=”postalcode”/></td>
<td><xsl:value-of select=”country”/></td>
<td><xsl:value-of select=”homephone”/></td>
<td><xsl:value-of select=”extension”/></td>
<td>
<xsl:choose>
<xsl:when test=”string-length( photo) > 0″>
<img>
<xsl:attribute name=”src”>
<xsl:text>getimage.aspx?employeeid=</xsl:text>
<xsl:value-of select=”employeeid”/>
</xsl:attribute>
</img>
</xsl:when>
<xsl:otherwise><xsl:value-of select=”photo”/></xsl:otherwise>
</xsl:choose>
<!–xsl:value-of select=”photo”/–>
</td>
<td>
<xsl:choose>
<xsl:when test=”string-length( notes) > 50″>
<xsl:value-of select=”substring(notes, 0, 50)”/><xsl:text>…</xsl:text>
</xsl:when>
<xsl:otherwise><xsl:value-of select=”notes”/></xsl:otherwise>
</xsl:choose>
<!–xsl:value-of select=”notes”/–>
</td>
<td>
<xsl:variable name=”photopath”><xsl:value-of select=”photopath”/></xsl:variable>
<xsl:if test=”string-length($photopath) > 0″>
<a href=”{$photopath}”>
<xsl:value-of select=”$photopath”/>
</a>
</xsl:if>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
由于xslt文件中无法直接对二进制数据做处理,我这里采用了变通方法,使用<img src=”getimage.aspx?employeeid=1″/>这样的形式,以便从另一个asp.net页面中读取图片数据并显示图像。
getimage.aspx.cs中的关键代码:
private void page_load(object sender, system.eventargs e)
{
string employeeid = request.querystring[“employeeid”];
if(employeeid == string.empty || employeeid == null)
{
return;
}
byte[] imgbytearray = getimage(employeeid);
response.contenttype=”image/jpeg”;
int offset = 78;
//读取图片并作图片格式转换,原图是bmp图,在网页中显示使用jpg图片,同时使图片感官效果优化:
system.io.memorystream mstream = new system.io.memorystream ();
system.io.memorystream stream = new system.io.memorystream ();
mstream.write(imgbytearray, offset, imgbytearray.length – offset);
system.drawing.bitmap bmp = new system.drawing.bitmap(mstream);
bitmap bmptmp = new bitmap(bmp.width/2, bmp.height/2);//尺寸缩小为50%
graphics g = graphics.fromimage(bmptmp);
g.compositingquality = compositingquality.highquality;
g.interpolationmode = interpolationmode.highqualitybicubic;
rectangle destrect = new rectangle(0, 0, bmptmp.width, bmptmp.height);
rectangle srcrect = new rectangle(0, 0, bmp.width, bmp.height);
g.drawimage(bmp, destrect, srcrect, graphicsunit.pixel);
bmptmp.save(stream, system.drawing.imaging.imageformat.jpeg );
g.dispose();
bmp.dispose();
byte[] bytereturn = stream.toarray();
mstream.close();
stream.close();
response.outputstream.write(bytereturn, 0, bytereturn.length);
response.end();
}
private byte[] getimage(string employeeid)
{
connstring = system.configuration.configurationsettings.appsettings[ “connstring” ];
using (sqlconnection conn = new sqlconnection(connstring))
{
string sqlselect = “select photo from employees where employeeid = ” + employeeid;
sqlcommand cmd = conn.createcommand();
cmd.commandtext = sqlselect;
conn.open();
using (sqldatareader dr = cmd.executereader(commandbehavior.singlerow))
{
if(dr.read())
{
if(dr[0] != null)
{
byte[] byteimg = (byte[])dr[0];
return byteimg;
}
}
}
}
return null;
}
最终效果图: