AJAX 照片专辑项目






4.85/5 (10投票s)
该项目展示了如何使用 AJAX XmlHttpRequest 创建照片集和幻灯片。
引言
本文介绍了几种创建简单照片集和幻灯片的技术。
- 将图像保存并检索到 MS SQL Server 数据库。
- 调整图像大小。
- 使用 AJAX
XmlHttpRequest
从数据库检索图像。 - 使用 AJAX
UpdatePanel
和ScriptManager
在不刷新网页的情况下从数据库检索图像。
背景
AjaxPhotoAlbum 项目的开发旨在展示几项有用的技术。
- 示例照片集由缩略图和一个图像控件组成,用于浏览大图。
- 用户还可以单击“上一个”(<<)和“下一个”(>>)链接按钮来获取大图占位符中的上一个/下一个图像。整个控件放置在 AJAX
UpdatePanel
中,因此,即使图像是在回发事件中从数据库检索的,网页也不会刷新,只有大图控件会被新图像更新。 - 用户还可以运行幻灯片,它将从数据库中以从 Interval 下拉列表控件中选择的间隔检索图像。在这种情况下,AJAX
XmlHttpRequst
对象用于发送请求并使用后台网页 GetSelectedImage.aspx 获取响应。 - 照片集的图像存储在数据库中。要将图像添加到数据库,用户可以单击“添加新图像”按钮。原始图像将被调整为两种不同的尺寸 - 小尺寸(宽度 120 像素 - 用于缩略图)和大尺寸(宽度 250 像素 - 用于大图占位符)并保存到数据库的“Images”表中。
- 当需要从数据库检索图像时(无论是用于缩略图还是大图控件),都会将其读入字节数组,然后写入网页“ImagePage.aspx”,该网页的链接又用作网页上图像控件的“
src
”属性。
当用户将鼠标悬停在缩略图图像上时,大图也会填充所选图像。大图使用网页 GetSelectedImage.aspx 通过 AJAX XmlHttpRequest
从数据库中检索。
使用代码
对于这个项目,创建了一个 MS SQL Server 数据库“AjaxPhotoAlbum”,其中只有一个表“Images”。创建表的脚本可以在下载包中找到,但下面是“Images”表的描述。
列名 | 数据类型 |
ImageId |
int (主键,标识种子 = 1) |
ImageSmall |
图像 |
ImageLarge |
图像 |
此表将保存 AjaxPhotoAlbum 项目的图像。这里显示了 web.config 文件中的连接字符串。
<appSettings>
<add key="DSN"
value="server=localhost;Integrated Security=SSPI;database=AjaxPhotoAlbum"/>
</appSettings>
完整的项目结构包括四个层。
- 表示层:Default.aspx
- GetSelectedImage.aspx(提供 AJAX
XmlHttpRequest
调用中实际回发的网页) - ImagePage.aspx(在图像控件中显示从数据库检索到的图像的网页)
- WebControls
- PhotoAlbumControl.ascx
- SlideShow.ascx
- JavaScript
- AjaxImage.js
- 图像
- CSS
- 业务逻辑层:App_Code
- ImageClass.cs
- 数据访问层:App_Code
- SQLHelper.cs
- MS SQL Server 数据库:AjaxPhotoAlbum 数据库
- Images 表
BL
DAL
PhotoAlbumControl.ascx 放置在 AJAX UpdatePanel
中的 Default.aspx 网页上。Default.aspx 还有一个 ScriptManager
控件。为了使 AJAX 控件正常工作,必须在 <system.web>
节点下包含 <httpHandlers>
部分。
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd"
validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
validate="false"/>
</httpHandlers>
通过上述设置,当用户单击“上一个”/“下一个”按钮(“<<”或“>>”)时,网页会回发但不会整体刷新。只有 imgPhoto
Web 控件会被新选定的图像刷新。缩略图构建为 DataList
控件。图像 ID 从数据库检索,并在 DataList ItemDataBound()
事件中填充缩略图的“src
”、“onclick
”和“onmouseover
”属性。
protected void ThumbnailsItemDatabound(object sender, DataListItemEventArgs e)
{
Image tImage = (Image)dlThumbnails.Controls[e.Item.ItemIndex].Controls[3];
string ajaxServerUrl = "GetSelectedImage.aspx";
tImage.Attributes.Add("src", "ImagePage.aspx?s=s&id=" +
((DataRowView)e.Item.DataItem).Row.ItemArray[0].ToString());
tImage.Attributes.Add("onclick",
"getImage(‘" + ajaxServerUrl + "‘," +
((DataRowView)e.Item.DataItem).Row.ItemArray[0].ToString() + ")");
tImage.Attributes.Add("onmouseover", "getImage(‘" +
ajaxServerUrl + "‘," +
((DataRowView)e.Item.DataItem).Row.ItemArray[0].ToString() + ")");
}
“onclick
”和“onmouseover
”缩略图图像属性在 AJAX JavaScript 函数 getImage()
中调用,以使用缩略图中选定的图像填充大图控件 impPhoto
。getImage()
JavaScript 函数向网页 GetSelectedImage.aspx 发送 AJAX XmlHttpRequest
,该网页进而执行实际回发以从数据库检索请求的图像 ID。
//Sending information to server
function getImage(AjaxServerUrl, id)
{
var url = AjaxServerUrl + "?id=" + id
imageClient.open("GET", url);
imageClient.onreadystatechange = getImageBack;
imageClient.send(null);
}
GetSelectedImage.aspx 网页检索所需的图像 ID,并以 XML 格式作为响应返回。
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Tirex;
public partial class GetSelectedImage : System.Web.UI.Page
{
DataSet ds = new DataSet();
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Response.ContentType = "text/xml";
int id = 0;
if (Request.Params["id"] != null)
{
id = Int32.Parse(Request.Params["id"].ToString());
}
else
{
if (Session["ImageId"] != null)
{
id = Int32.Parse(Session["ImageId"].ToString());
}
id = ImageClass.GetImageId(id);
Session["ImageId"] = id.ToString();
}
Session["SelectedImageId"] = id.ToString();
Response.Write("<Root>");
Response.Write("<ImageId>");
Response.Write(id);
Response.Write("</ImageId>");
Response.Write("</Root>");
}
}
响应由 getImageBack()
JavaScript 函数接收并解析。请考虑 Internet Explorer 和 Firefox 处理响应方式的差异。
//Waiting and processing server response
function getImageBack(response)
{
var imageId = 0;
try
{
if(imageClient.readyState == COMPLETE && imageClient.status == OK)
{
//branch for Firefox version
if (document.implementation.createDocument)//Firefox
{
//Get Image
var xmlElementImageId =
imageClient.responseXML.getElementsByTagName(
"Root")[0].childNodes[0];
imageId = xmlElementImageId.textContent;
}
//branch for IE/Windows ActiveX version
else if (document.all)//IE
{
xmlDocument = new ActiveXObject(‘Microsoft.XMLDOM‘);
xmlDocument.async = false;
//The responseText is loaded into XML document
xmlDocument.loadXML(imageClient.responseText);
//Get Image
var xmlElementImageId =
xmlDocument.selectSingleNode(‘Root/ImageId‘);
imageId = xmlElementImageId.text;
}
var imgPhoto;
imgPhoto = window.document.getElementById(
"PhotoAlbumControl1_imgPhoto");
imgPhoto.src = "ImagePage.aspx?s=l&id=" + imageId;
}
}
catch(err)
{
alert(err.message);
}
}
图像以字节数组的形式从数据库检索,并写入 Image.aspx 网页,该网页又用作缩略图图像或 imgPhoto
图像控件的“src
”属性。
private void Page_Load(object sender, System.EventArgs e)
{
string sSQL = "";
SqlDataReader drData = null;
SqlCommand cmd = null;
SqlConnection cnn = new SqlConnection(SqlHelper.connectionString());
cnn.Open();
string id = Request.Params["id"].ToString();
string s = Request.Params["s"].ToString();
if (s == "s")
{
sSQL = "SELECT ImageSmall FROM Images WHERE ImageId=" + id.ToString();
}
else
{
sSQL = "SELECT ImageLarge FROM Images WHERE ImageId=" + id.ToString();
}
//try
//{
using (cmd = new SqlCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = sSQL;
cmd.Connection = cnn;
drData = cmd.ExecuteReader();
if (drData.Read())
{
if (s == "s")
{
Response.BinaryWrite((byte[])drData["ImageSmall"]);
}
else
{
Response.BinaryWrite((byte[])drData["ImageLarge"]);
}
}
cnn.Close();
}
//}
//catch { }
}
用户可以通过“添加新图像”按钮向照片集添加新图像。要将图像保存到数据库,它们首先被读取到字节数组中。
len1 = File1.PostedFile.ContentLength;
imageSmall = new byte[len1];
imageLarge = new byte[len1];
File1.PostedFile.InputStream.Read(imageLarge, 0, len1);
在保存到数据库之前,将上传的图像调整到所需的尺寸。
imageSmall = ImageClass.ResizeImage(250, imageLarge);
imageLarge = ImageClass.ResizeImage(250, imageLarge);
public static byte[] ResizeImage(int newWidth, byte[] pictureBytes)
{
Bitmap b = (Bitmap)Bitmap.FromStream(new MemoryStream(pictureBytes));
int imageWidth = b.Width;
int imageHeight = b.Height;
double newHeightD = Convert.ToDouble(newWidth) /
Convert.ToDouble(imageWidth) * Convert.ToDouble(imageHeight);
int newHeight = Convert.ToInt32(newHeightD);
Bitmap output = new Bitmap(b, new Size(newWidth, newHeight));
MemoryStream ms = new MemoryStream();
output.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bmpBytes = ms.GetBuffer();
output.Dispose();
ms.Close();
return bmpBytes;
}
可以在 http://www.realproject.ca/default.aspx?contentid=1660 处查看在线示例。