Dynamiskt bildhämtning
Förord
En av de största milstolparna inom webbutveckling var när databasen introducerades i ekvationen. Informationen på webbsidorna kan flyttas ut från designen och återanvändas på flera olika sidor. Om en förändring i informationen behöver genomföras så sker ändringen på ett ställe i databasen, och återspeglas på alla ställen som använder den. En annan viktig del av de flesta webbsidorna är bilderna som används. Samma problem kan uppstå med bilder som med text när man behöver göra förändringar, så som att byta namn på en bild eller byta sökvägen till bildfilen.Innehåll
Genom att koda in namnet och sökvägen till en bild på webbsidor, så medför en förändring av en av de två sakerna att man måste gå tillbaka till koden och uppdatera den. En klar fördel hade varit om man kunnat flytta ut denna informationen till en extern källa, så som en databas, och tilldela varje bild en fast referens som inte förändras.
Vad är det som händer när en img-tagg laddas in på en webbsida? En förfrågan skickas till servern med bildens namn och som svar kommer bilden som en ström av information, vilket är filen som kopieras från servern till klienten.
Funktionen som kan utnyttjas för att byta ut bildens riktig namn med en fast referens, så som ett id-nummer, är att den information som skickas till webbservern när en bild skall hämtas behöver inte vara det riktiga namnet på bilden, utan kan istället vara namnet på en annan sida som strömmar tillbaka bildinformationen.
Jag kommer i denna artikel visa hur man kan bygga en enkel sida som tar emot ett id-nummer när den anropas och skickar tillbaka bildinformationen till webbsidan. Det id-nummer som skickas med kommer att användas för att slå upp bildnamnet i en databas med hjälp av en lagrad procedur.
Det första som behövs göras är att sätta upp en enkel databas, i detta fallet en SQL Server databas, som kommer användas lagra bildnamnen, samt skapa den lagrade procedur som omvandlar id-numret till ett bildnamn.
[SQL]
[SQL]
Den del som kommer att ansvara för att skicka tillbaka bildinformationen till webbsidan är en helt vanlig ASP.NET sida som har namnet ImageResource.aspx. Sidan förväntar sig att bildens id-nummer skickas med till sidans QueryString med namnet imageid när den anropas.
Ett exempel på hur ImageResource.aspx kommer att användas på en webbsida för att visa en bild är följande
[ASP.NET]
Sidans funktionaliteten byggs in i code-behind delen och saknar helt och hållet HTML, då dess enda syfte är att strömma tillbaka bildinformationen när den anropas.
[C#]
[VB.NET]
Den absolut viktigaste delen av allt är att det verkligen skickas med ett id-nummer för den bilden som skall hämtas och skickas tillbaka. Kommer inte ett giltigt id-nummer med, eller om ett id-nummer inte skickas med över huvudtaget, så får man problem.
En lösning på detta är att använda en speciell bild som visas när den önskade bilden inte finns, eller inget id-nummer skickas med. Denna bild skulle kunna visa texten Bild saknas eller något liknande. För att enkelt kunna illustrera detta kommer namnet på denna bild att vara hårdkodat och inte ligga i databasen.
[C#]
[VB.NET]
Grunden för sidan är nu klar och har utrustats med en variable för att lagra namnet på den bilden som skall visas, samt en kontroll för att vara säker på att ett id-nummer har skickats med till sidan. Variabeln som används för att lagra namnet på bilden har fått ett standardvärde som är namnet på den bild som skall visas om ett felaktigt id-nummer skickats med in eller om det inte skickats med över huvudtaget.
Nästa steg är att upprätta en uppkoppling mot databasen, som kommer att användas för att slå upp namnet på den bild som är associerad med det angivna id-numret. Den connectionstring som används för att upprätta en uppkoppling mot databasen har flyttats ut till web.config filen för att enklare kunna administreras.
[WEB.CONFIG]
[C#]
[VB.NET]
För att slå upp namnet på den bild med det angivna id-numret, så används en parametriserad SQL fråga som byggs upp med hjälp av ett SqlCommand objekt. I början av artikeln skapade vi en lagrad procedur med namnet GetImageById som används. Uppkopplingen mot databasen skapas, samt att koden för att stänga den när databasanropet är klart läggs in.
[C#]
[VB.NET]
När alla förberedelser för databasanropet är klara är det dags att genomföra det. I detta fallet används metoden ExecuteScalar som returnerar första kolumnen i första raden av det resultat som anropet returnerar. Det fungerar utmärkt här då SQL frågan kan som mest returnera en rad och vår lagrade procedur returnerar bara en kolumn.
Resultatet kontrolleras så att ett bildnamn returneras och ytterligare en kontroll genomförs så att bilden verkligen finns innan den skickas tillbaka. Först när allt är kontrollerat så byts standardnamnet ut mot namnet på den önskade bilden. Bilderna har placerats i en underkatalog till webbsidan, med namnet images.
[C#]
[VB.NET]
När allt är klart, vare sig bilden till det inskickade id-numret kunde hittas eller inte, så skall bildinformationen strömmas tillbaka till webbsidan. Koden för att göra detta placeras utanför alla kontroller då den alltid skall exekveras på grund av att en standardbild returneras i värsta fall.
[C#]
[VB.NET]
ImageResource.aspx är nu klar att användas på en webbsida. Om bilderna skulle behöva byta namn eller sökväg till var de lagras så är det bara att uppdatera databasen och förändringen återspeglas på webbsidan utan att behöva modifiera den.
I denna artikel har bilderna placerats i en underkatalog, med namnet images och det fungerar utmärkt att skapa underkataloger till denna och lägga in den relativa sökvägen till en bild i databasen.
Vad är det som händer när en img-tagg laddas in på en webbsida? En förfrågan skickas till servern med bildens namn och som svar kommer bilden som en ström av information, vilket är filen som kopieras från servern till klienten.
Funktionen som kan utnyttjas för att byta ut bildens riktig namn med en fast referens, så som ett id-nummer, är att den information som skickas till webbservern när en bild skall hämtas behöver inte vara det riktiga namnet på bilden, utan kan istället vara namnet på en annan sida som strömmar tillbaka bildinformationen.
Jag kommer i denna artikel visa hur man kan bygga en enkel sida som tar emot ett id-nummer när den anropas och skickar tillbaka bildinformationen till webbsidan. Det id-nummer som skickas med kommer att användas för att slå upp bildnamnet i en databas med hjälp av en lagrad procedur.
Det första som behövs göras är att sätta upp en enkel databas, i detta fallet en SQL Server databas, som kommer användas lagra bildnamnen, samt skapa den lagrade procedur som omvandlar id-numret till ett bildnamn.
[SQL]
CREATE TABLE [Images] (
[Id] [int] IDENTITY (1, 1) NOT NULL ,
[Image] [varchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
CONSTRAINT [PK_Images] PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
) ON [PRIMARY]
[SQL]
CREATE PROCEDURE dbo.GetImageById
(
@ImageId int
)
AS
SET NOCOUNT ON
SELECT [Image] From Images WHERE [Images].[Id] = @ImageId
Den del som kommer att ansvara för att skicka tillbaka bildinformationen till webbsidan är en helt vanlig ASP.NET sida som har namnet ImageResource.aspx. Sidan förväntar sig att bildens id-nummer skickas med till sidans QueryString med namnet imageid när den anropas.
Ett exempel på hur ImageResource.aspx kommer att användas på en webbsida för att visa en bild är följande
[ASP.NET]
Sidans funktionaliteten byggs in i code-behind delen och saknar helt och hållet HTML, då dess enda syfte är att strömma tillbaka bildinformationen när den anropas.
[C#]
public class ImageResource : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
}
}
[VB.NET]
Public Class ImageResource
Inherits System.Web.UI.Page
Private imageName As String = "saknas.jpg"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
End Class
Den absolut viktigaste delen av allt är att det verkligen skickas med ett id-nummer för den bilden som skall hämtas och skickas tillbaka. Kommer inte ett giltigt id-nummer med, eller om ett id-nummer inte skickas med över huvudtaget, så får man problem.
En lösning på detta är att använda en speciell bild som visas när den önskade bilden inte finns, eller inget id-nummer skickas med. Denna bild skulle kunna visa texten Bild saknas eller något liknande. För att enkelt kunna illustrera detta kommer namnet på denna bild att vara hårdkodat och inte ligga i databasen.
[C#]
public class ImageResource : System.Web.UI.Page
{
private string imageName = "saknas.jpg";
private void Page_Load(object sender, System.EventArgs e)
{
if( this.Request.QueryString["imageid"] != null )
{
}
}
}
[VB.NET]
Public Class ImageResource
Inherits System.Web.UI.Page
Private imageName As String = "saknas.jpg"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Me.Request.QueryString.Item("imageid") Is Nothing Then
End If
End Sub
End Class
Grunden för sidan är nu klar och har utrustats med en variable för att lagra namnet på den bilden som skall visas, samt en kontroll för att vara säker på att ett id-nummer har skickats med till sidan. Variabeln som används för att lagra namnet på bilden har fått ett standardvärde som är namnet på den bild som skall visas om ett felaktigt id-nummer skickats med in eller om det inte skickats med över huvudtaget.
Nästa steg är att upprätta en uppkoppling mot databasen, som kommer att användas för att slå upp namnet på den bild som är associerad med det angivna id-numret. Den connectionstring som används för att upprätta en uppkoppling mot databasen har flyttats ut till web.config filen för att enklare kunna administreras.
[WEB.CONFIG]
[C#]
public class ImageResource : System.Web.UI.Page
{
private string imageName = "saknas.jpg";
private void Page_Load(object sender, System.EventArgs e)
{
if( this.Request.QueryString["imageid"] != null )
{
string connectionString =
(string)ConfigurationSettings.AppSettings["connectionString"];
using( SqlConnection db = new SqlConnection(connectionString) )
{
}
}
}
}
[VB.NET]
Public Class ImageResource
Inherits System.Web.UI.Page
Private imageName As String = "saknas.jpg"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Me.Request.QueryString.Item("imageid") Is Nothing Then
Dim connectionString As String
connectionString = CType(ConfigurationSettings.AppSettings.Item("connectionString"), String)
Dim db As New SqlConnection(connectionString)
End If
End Sub
End Class
För att slå upp namnet på den bild med det angivna id-numret, så används en parametriserad SQL fråga som byggs upp med hjälp av ett SqlCommand objekt. I början av artikeln skapade vi en lagrad procedur med namnet GetImageById som används. Uppkopplingen mot databasen skapas, samt att koden för att stänga den när databasanropet är klart läggs in.
[C#]
public class ImageResource : System.Web.UI.Page
{
private string imageName = "saknas.jpg";
private void Page_Load(object sender, System.EventArgs e)
{
if( this.Request.QueryString["imageid"] != null )
{
string connectionString =
(string)ConfigurationSettings.AppSettings["connectionString"];
using( SqlConnection db = new SqlConnection(connectionString) )
{
SqlCommand imageCommand =
new SqlCommand("GetImageById", db);
imageCommand.CommandType = CommandType.StoredProcedure;
imageCommand.Parameters.Add(new SqlParameter("@ImageId", SqlDbType.Int, 4));
imageCommand.Parameters["@ImageId"].Value =
Convert.ToInt32(this.Request.QueryString["imageid"]);
db.Open();
if( db.State == ConnectionState.Open )
{
db.Close();
}
}
}
}
}
[VB.NET]
Public Class ImageResource
Inherits System.Web.UI.Page
Private imageName As String = "saknas.jpg"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Me.Request.QueryString.Item("imageid") Is Nothing Then
Dim connectionString As String
connectionString = CType(ConfigurationSettings.AppSettings.Item("connectionString"), String)
Dim db As New SqlConnection(connectionString)
Dim imageCommand As New SqlCommand("GetImageById", db)
imageCommand.CommandType = CommandType.StoredProcedure
imageCommand.Parameters.Add(New SqlParameter("@ImageId", SqlDbType.Int, 4))
imageCommand.Parameters.Item("@ImageId").Value = CType(Me.Request.QueryString.Item("imageid"), Integer)
db.Open()
If (db.State = ConnectionState.Open) Then
db.Close()
End If
End If
End Sub
End Class
När alla förberedelser för databasanropet är klara är det dags att genomföra det. I detta fallet används metoden ExecuteScalar som returnerar första kolumnen i första raden av det resultat som anropet returnerar. Det fungerar utmärkt här då SQL frågan kan som mest returnera en rad och vår lagrade procedur returnerar bara en kolumn.
Resultatet kontrolleras så att ett bildnamn returneras och ytterligare en kontroll genomförs så att bilden verkligen finns innan den skickas tillbaka. Först när allt är kontrollerat så byts standardnamnet ut mot namnet på den önskade bilden. Bilderna har placerats i en underkatalog till webbsidan, med namnet images.
[C#]
public class ImageResource : System.Web.UI.Page
{
private string imageName = "saknas.jpg";
private void Page_Load(object sender, System.EventArgs e)
{
if( this.Request.QueryString["imageid"] != null )
{
string connectionString =
(string)ConfigurationSettings.AppSettings["connectionString"];
using( SqlConnection db = new SqlConnection(connectionString) )
{
SqlCommand imageCommand =
new SqlCommand("GetImageById", db);
imageCommand.CommandType = CommandType.StoredProcedure;
imageCommand.Parameters.Add(new SqlParameter("@ImageId", SqlDbType.Int, 4));
imageCommand.Parameters["@ImageId"].Value =
Convert.ToInt32(this.Request.QueryString["imageid"]);
db.Open();
if( db.State == ConnectionState.Open )
{
object imageDbName =
imageCommand.ExecuteScalar();
if( imageDbName != null )
{
if( File.Exists(Server.MapPath("images/" + (string)imageDbName) ))
this.imageName = (string)imageDbName;
}
db.Close();
}
}
}
}
}
[VB.NET]
Public Class ImageResource
Inherits System.Web.UI.Page
Private imageName As String = "saknas.jpg"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Me.Request.QueryString.Item("imageid") Is Nothing Then
Dim connectionString As String
connectionString = CType(ConfigurationSettings.AppSettings.Item("connectionString"), String)
Dim db As New SqlConnection(connectionString)
Dim imageCommand As New SqlCommand("GetImageById", db)
imageCommand.CommandType = CommandType.StoredProcedure
imageCommand.Parameters.Add(New SqlParameter("@ImageId", SqlDbType.Int, 4))
imageCommand.Parameters.Item("@ImageId").Value = CType(Me.Request.QueryString.Item("imageid"), Integer)
db.Open()
If (db.State = ConnectionState.Open) Then
Dim imageDbName As Object
imageDbName = imageCommand.ExecuteScalar()
If Not imageDbName Is Nothing Then
If File.Exists(Server.MapPath("images/" & CType(imageDbName, String))) Then
Me.imageName = CType(imageDbName, String)
End If
End If
db.Close()
End If
End If
End Sub
End Class
När allt är klart, vare sig bilden till det inskickade id-numret kunde hittas eller inte, så skall bildinformationen strömmas tillbaka till webbsidan. Koden för att göra detta placeras utanför alla kontroller då den alltid skall exekveras på grund av att en standardbild returneras i värsta fall.
[C#]
public class ImageResource : System.Web.UI.Page
{
private string imageName = "saknas.jpg";
private void Page_Load(object sender, System.EventArgs e)
{
if( this.Request.QueryString["imageid"] != null )
{
string connectionString =
(string)ConfigurationSettings.AppSettings["connectionString"];
using( SqlConnection db = new SqlConnection(connectionString) )
{
SqlCommand imageCommand =
new SqlCommand("GetImageById", db);
imageCommand.CommandType = CommandType.StoredProcedure;
imageCommand.Parameters.Add(new SqlParameter("@ImageId", SqlDbType.Int, 4));
imageCommand.Parameters["@ImageId"].Value =
Convert.ToInt32(this.Request.QueryString["imageid"]);
db.Open();
if( db.State == ConnectionState.Open )
{
object imageDbName =
imageCommand.ExecuteScalar();
if( imageDbName != null )
{
if( File.Exists(Server.MapPath("images/" + (string)imageDbName) ))
this.imageName = (string)imageDbName;
}
db.Close();
}
}
}
Bitmap outputImage =
(Bitmap)Bitmap.FromFile(Server.MapPath("images/" + this.imageName));
outputImage.Save(this.Response.OutputStream, outputImage.RawFormat);
}
}
[VB.NET]
Public Class ImageResource
Inherits System.Web.UI.Page
Private imageName As String = "saknas.jpg"
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Me.Request.QueryString.Item("imageid") Is Nothing Then
Dim connectionString As String
connectionString = CType(ConfigurationSettings.AppSettings.Item("connectionString"), String)
Dim db As New SqlConnection(connectionString)
Dim imageCommand As New SqlCommand("GetImageById", db)
imageCommand.CommandType = CommandType.StoredProcedure
imageCommand.Parameters.Add(New SqlParameter("@ImageId", SqlDbType.Int, 4))
imageCommand.Parameters.Item("@ImageId").Value = CType(Me.Request.QueryString.Item("imageid"), Integer)
db.Open()
If (db.State = ConnectionState.Open) Then
Dim imageDbName As Object
imageDbName = imageCommand.ExecuteScalar()
If Not imageDbName Is Nothing Then
If File.Exists(Server.MapPath("images/" & CType(imageDbName, String))) Then
Me.imageName = CType(imageDbName, String)
End If
End If
db.Close()
End If
End If
Dim outputImage As Bitmap
outputImage = CType(Bitmap.FromFile(Server.MapPath("images/" & Me.imageName)), Bitmap)
outputImage.Save(Me.Response.OutputStream, outputImage.RawFormat)
End Sub
End Class
ImageResource.aspx är nu klar att användas på en webbsida. Om bilderna skulle behöva byta namn eller sökväg till var de lagras så är det bara att uppdatera databasen och förändringen återspeglas på webbsidan utan att behöva modifiera den.
I denna artikel har bilderna placerats i en underkatalog, med namnet images och det fungerar utmärkt att skapa underkataloger till denna och lägga in den relativa sökvägen till en bild i databasen.
0 Kommentarer