Silverlight的保存和检索图像从IsolatedStorag
时间:2010-08-17 来源:l2010q2010
在,我的一个以前的文章 从数据库中显示图像在Silverlight 2中,我们探讨如何从拉数据库图像使用Silverlight。 但是,这种方法速度慢,因为该数据库被击中每次用户请求一个员工形象。 在这篇文章中,我们将看到另一种方法,我们将使用IsolatedStorage来存储和检索图像。 一旦图像被从数据库提取和IsolatedStorage存储在所有后续请求可以被路由到IsolatedStorage,这使得超快速的反应,因为图像机提取现正从你的本地磁盘。 如果您是新的IsolatedStorage,读了更多的优势约 在这里。 我们将首先创建一个图像处理程序,将毒品从该数据库中图像的第一个请求。 我们将使用WebClient类来检索图像使用此处理。 这些图像将被储存在IsolatedStorage。 我们将利用在罗斯文数据库中的Employees表的使用。 第1步: 打开Visual Studio 2008>“文件>”新建项目“>选择语言(C#或VB)”>选择'的Silverlight>“的项目类型的模板,选择'的Silverlight应用程序的。 键入一个名称'ImagesInIsolatedStorage'和确定位置的项目,然后单击。 注:如果您无法查看模板,你没有安装Visual Studio 2008的微软Silverlight工具。 看看这个 链接 ,看看如何获得它。 第2步: 你将看到一个默认的页面叫做'的Page.xaml'获得创建。 创建一个几行和列,并添加一些像图像控制,TextBlock和按钮里面的网格。 TextBlock的将被用来显示状态信息的按钮会触发一个形象,而将获取控件显示在图像。 经过几年的布局设置属性,标记的Page.xaml的将类似于以下内容:
<UserControl x:Class="ImagesInIsolatedStorage.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="400" Height="300"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="200"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Image x:Name="img1" Grid.Row="0" Grid.ColumnSpan="2" Visibility="Visible"></Image> <TextBlock x:Name="txtStatus" Grid.Row="1" Grid.Column="0"/> <Button x:Name="btnDisplayImg" Grid.Row="1" Grid.Column="1" Height="100" Width="100" Content="Display" Click="btnDisplayImg_Click"></Button> </Grid> </UserControl>
第3步: 由于我们是检索数据库中的图像时,我们会需要一个连接字符串到数据库。 添加下面的连接字符串到web.config中
<connectionStrings> <add name="NorthwindConnectionString" connectionString="Data Source=(local);Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient"/> </connectionStrings>
第4步: 我们将使用一个HttpHandler拉数据库的图像从。 处理程序提供了许多灵活性的同时访问服务器端资源。 要创建一个HttpHandler,右键单击项目AccessImagesInDatabase.Web>“添加新项目>通用处理器> DisplayImage.ashx。 下面的代码添加到处理程序。
C# using System; using System.ComponentModel; using System.Configuration; using System.Data; using System.Data.SqlClient; using System.Drawing; using System.Drawing.Imaging; using System.Web; using System.Web.Services; namespace AccessImagesInDatabase.Web { ///<summary> /// Summary description for $codebehindclassname$ ///</summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class DisplayImage : IHttpHandler { byte[] empPic = null; long seq = 0; public void ProcessRequest(HttpContext context) { Int32 empno; if (context.Request.QueryString["id"] != null) empno = Convert.ToInt32(context.Request.QueryString["id"]); else throw new ArgumentException("No parameter specified"); // Convert Byte[] to Bitmap Bitmap newBmp = ConvertToBitmap(ShowEmpImage(empno)); if (newBmp != null) { newBmp.Save(context.Response.OutputStream, ImageFormat.Jpeg); newBmp.Dispose(); } } // Convert byte array to Bitmap (byte[] to Bitmap) protected Bitmap ConvertToBitmap(byte[] bmp) { if (bmp != null) { TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap)); Bitmap b = (Bitmap)tc.ConvertFrom(bmp); return b; } return null; } public byte[] ShowEmpImage(int empno) { string conn = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString; SqlConnection connection = new SqlConnection(conn); string sql = "SELECT photo FROM Employees WHERE EmployeeID = @ID"; SqlCommand cmd = new SqlCommand(sql, connection); cmd.CommandType = CommandType.Text; cmd.Parameters.AddWithValue("@ID", empno); connection.Open(); SqlDataReader dr = cmd.ExecuteReader(); if (dr.Read()) { seq = dr.GetBytes(0, 0, null, 0, int.MaxValue) - 1; empPic = new byte[seq + 1]; dr.GetBytes(0, 0, empPic, 0, Convert.ToInt32(seq)); connection.Close(); } return empPic; } public bool IsReusable { get { return false; } } } } VB.NET Imports System Imports System.ComponentModel Imports System.Configuration Imports System.Data Imports System.Data.SqlClient Imports System.Drawing Imports System.Drawing.Imaging Imports System.Web Imports System.Web.Services Namespace AccessImagesInDatabase.Web ''' <summary> ''' Summary description for $codebehindclassname$ ''' </summary> <WebService(Namespace := "http://tempuri.org/"), WebServiceBinding(ConformsTo := WsiProfiles.BasicProfile1_1)> _ Public Class DisplayImage Implements IHttpHandler Private empPic() As Byte = Nothing Private seq As Long = 0 Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest Dim empno As Int32 If context.Request.QueryString("id") IsNot Nothing Then empno = Convert.ToInt32(context.Request.QueryString("id")) Else Throw New ArgumentException("No parameter specified") End If ' Convert Byte[] to Bitmap Dim newBmp As Bitmap = ConvertToBitmap(ShowEmpImage(empno)) If newBmp IsNot Nothing Then newBmp.Save(context.Response.OutputStream, ImageFormat.Jpeg) newBmp.Dispose() End If End Sub ' Convert byte array to Bitmap (byte[] to Bitmap) Protected Function ConvertToBitmap(ByVal bmp() As Byte) As Bitmap If bmp IsNot Nothing Then Dim tc As TypeConverter = TypeDescriptor.GetConverter(GetType(Bitmap)) Dim b As Bitmap = CType(tc.ConvertFrom(bmp), Bitmap) Return b End If Return Nothing End Function Public Function ShowEmpImage(ByVal empno As Integer) As Byte() Dim conn As String = ConfigurationManager.ConnectionStrings("NorthwindConnectionString").ConnectionString Dim connection As New SqlConnection(conn) Dim sql As String = "SELECT photo FROM Employees WHERE EmployeeID = @ID" Dim cmd As New SqlCommand(sql, connection) cmd.CommandType = CommandType.Text cmd.Parameters.AddWithValue("@ID", empno) connection.Open() Dim dr As SqlDataReader = cmd.ExecuteReader() If dr.Read() Then seq = dr.GetBytes(0, 0, Nothing, 0, Integer.MaxValue) - 1 empPic = New Byte(seq){} dr.GetBytes(0, 0, empPic, 0, Convert.ToInt32(seq)) connection.Close() End If Return empPic End Function Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property End Class End Namespace
从数据库的图像检索的步骤,使用处理程序如下: 1。雇员的形象,是通过检索查询字符串传递到处理程序。 我们使用的Request.QueryString [“身份证”]的处理程序来检索雇员网址(emp_id)。 该ID,然后传递到'ShowEmpImage()'方法,从而使图像从数据库提取和使用SqlDataReader的一个字节[]返回的对象。 2。我们通过这个字节[]到ConvertToBitmap()函数,我们使用TypeConverter类字节数组转换为位图。 3。最后一步是将图像保存到页面的输出流,并注明图片格式如下所示convBmp.Save(context.Response.OutputStream,ImageFormat.Jpeg) 注:Silverlight不支持。BMP图像。 基于这个原因,我们设置ImageFormat为JPEG图像,同时节省的OutputStream中。 第五步: 接下来的步骤是使用WebClient类获取如下所示的形象。 回到Page.Xaml.cs或VB:
C# WebClient wc; int imgNo = 3; public Page() { InitializeComponent(); } private void btnDisplayImg_Click(object sender, RoutedEventArgs e) { IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication(); string imgnm = "Emp" + imgNo + ".jpg"; if (isoStore.FileExists(imgnm)) { txtStatus.Text = "Image fetched from Isolated Storage"; DisplayImage(imgNo, imgnm); } else { string imgUri = "http://localhost:49858/DisplayImage.ashx?id=" + imgNo; wc = new WebClient(); wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted); wc.OpenReadAsync(new Uri(imgUri, UriKind.Absolute)); } } VB.NET Private wc As WebClient Private imgNo As Integer = 3 Private Sub btnDisplayImg_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Dim isoStore As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication() Dim imgnm As String = "Emp" & imgNo & ".jpg" If isoStore.FileExists(imgnm) Then txtStatus.Text = "Image fetched from Isolated Storage" DisplayImage(imgNo, imgnm) Else Dim imgUri As String = "http://localhost:49858/DisplayImage.ashx?id=" & imgNo wc = New WebClient() AddHandler wc.OpenReadCompleted, AddressOf wc_OpenReadCompleted wc.OpenReadAsync(New Uri(imgUri, UriKind.Absolute)) End If End Sub
在btnDisplayImg_Click事件,我们首先检查图像的要求是在IsolatedStorage。 如果图像存在,我们显示的图像使用DisplayImage()方法。 我们将看到DisplayImage()方法在一个时刻。 如果图像不存在,我们通过一个构造函数初始化WebClient的对象,添加OpenReadCompleted事件处理程序,然后提出要求改为1使用OpenReadAsync(服务)的形象。 该OpenReadAsyc接受一个URI这是在我们的例子路径1 ImageHandler。 图像检索使用ImageHandler。 我们通过一个查询字符串作为参数的处理程序的雇员(imgNo)。 注: 如果协议,路径或服务的端口号从Silverlight的应用程序不同的是,它是一个Silverlight的跨域调用研究。 你需要一个clientaccesspolicy.xml保存在服务的根服务器的托管,使跨域调用。 了解更多关于它在 这里。 在我们的例子中,我们一直都在相同的端口和路径(http://localhost:49858/) 第6步: 现在让我们添加功能OpenReadCompleted()和DisplayImage()方法。
C# void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { if (e.Error == null) { try { IsolatedStorageFile isof = IsolatedStorageFile.GetUserStoreForApplication(); bool? chkRes = CheckAndGetMoreSpace(e.Result.Length); if (chkRes == false) { throw new Exception("Cannot store image due to insufficient space"); } string imgName = "Emp" + imgNo + ".jpg"; // Save the image to Isolated Storage IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(imgName, FileMode.Create, isof); Int64 imgLen = (Int64)e.Result.Length; byte[] b = new byte[imgLen]; e.Result.Read(b, 0, b.Length); isfs.Write(b, 0, b.Length); isfs.Flush(); isfs.Close(); isof.Dispose(); txtStatus.Text = "Image fetched from Database"; DisplayImage(imgNo, imgName); } catch (Exception ex) { txtStatus.Text = "Error while fetching image"; } } } // Increase Isolated Storage Quota protected bool CheckAndGetMoreSpace(Int64 spaceReq) { IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication(); Int64 spaceAvail = store.AvailableFreeSpace; if (spaceReq > spaceAvail) { if (!store.IncreaseQuotaTo(store.Quota + spaceReq)) { return false; } return true; } return true; } protected void DisplayImage(int imgid, string imgnm) { using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication()) { using (IsolatedStorageFileStream isoStream = isoStore.OpenFile(imgnm, FileMode.Open)) { BitmapImage bmpImg = new BitmapImage(); bmpImg.SetSource(isoStream); img1.Source = bmpImg; } } } VB.NET Private Sub wc_OpenReadCompleted(ByVal sender As Object, ByVal e As OpenReadCompletedEventArgs) If e.Error Is Nothing Then Try Dim isof As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication() Dim chkRes As Nullable(Of Boolean) = CheckAndGetMoreSpace(e.Result.Length) If chkRes.GetValueOrDefault() = False Then Throw New Exception("Cannot store image due to insufficient space") End If Dim imgName As String = "Emp" & imgNo & ".jpg" ' Save the image to Isolated Storage Dim isfs As New IsolatedStorageFileStream(imgName, FileMode.Create, isof) Dim imgLen As Int64 = CLng(Fix(e.Result.Length)) Dim b(imgLen - 1) As Byte e.Result.Read(b, 0, b.Length) isfs.Write(b, 0, b.Length) isfs.Flush() isfs.Close() isof.Dispose() txtStatus.Text = "Image fetched from Database" DisplayImage(imgNo, imgName) Catch ex As Exception txtStatus.Text = "Error while fetching image" End Try End If End Sub ' Increase Isolated Storage Quota Protected Function CheckAndGetMoreSpace(ByVal spaceReq As Int64) As Boolean Dim store As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication() Dim spaceAvail As Int64 = store.AvailableFreeSpace If spaceReq > spaceAvail Then If (Not store.IncreaseQuotaTo(store.Quota + spaceReq)) Then Return False End If Return True End If Return True End Function Protected Sub DisplayImage(ByVal imgid As Integer, ByVal imgnm As String) Using isoStore As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication() Using isoStream As IsolatedStorageFileStream = isoStore.OpenFile(imgnm, FileMode.Open) Dim bmpImg As New BitmapImage() bmpImg.SetSource(isoStream) img1.Source = bmpImg End Using End Using End Sub
该OpenReadCompleted包含调用CheckAndGetMoreSpace()方法。 现在,默认情况下,有空间可用于对IsolatedStorage 1MB的Silverlight应用程序。 该CheckAndGetMoreSpace()方法计算所需的额外空间来存储图片,并请用户分配的空间。 然后,我们保存的图像到IsolatedStorage通过让每个图像IsolatedStorageFileStream并储存在一个字节数组中的数据。 最后isfs.Write()是用来写一个字节块的IsolatedStorageFileStream。 注意:如果你想知道如何访问IsolatedStorage并查看图像存储,然后在我的Vista中,文件夹的IsolatedStorage在这里: C:\用户\ Administrator.suprotim \应用程序数据\ LocalLow \微软\的Silverlight \是\ 和图像存储在: C:\用户\ Administrator.suprotim \应用程序数据\ LocalLow \微软\的Silverlight \是\ dr0ccmrn.kwc \ hr31wxjf.o0b \ 1 \ S的\ pdfknk1vnik4d0hl4zegmkxtszihwwgfemh5c4j4pphxq2pfxeaaaaea \ f 现在,在DisplayImage()方法,我们打开从IsolatedStorage所需图像,并设置成一个FileStream流直接来填充这对于使用'SetSource'BitmapImage图形源文件。 最后,我们设置img1.Source属性这一BitmapImage实例。
相关阅读 更多 +