ASP.NET

Automatisches Bereitstellen versionierter Downloads

Über ein UserControl und Dateimuster immer die aktuellste Datei anbieten

Webmaster, wie ich, die auf Ihrer Web-Site selbstentwickelte Tools zur Verfügung stellen, haben stets das gleiche Problem, wenn sie eine neue Version veröffentlichen wollen: neben der Erstellung des Downloads-Pakets, muss man auch noch den neuen Download über einen angepassten Link in die Seiten einbinden, sofern aus dem Dateinamen ersichtlich werden soll, um welche Version es sich handelt.

Mit etwas Code lässt sich das Deployment solcher Pakete aber auf den reinen FTP-Upload beschränken. Soll sich die Seite doch selbst den aktuellen Download heraussuchen...

In ASP.NET lässt sich das Ganze wunderbar in ein UserControl verpacken, sodaß man beim Entwickeln der Web-Seiten schnell einen neuen Download deklarieren kann, ohne erneut viel Code zu schreiben.

Beginnen wir damit, wie der Download-Link der versionierten Datei aussehen soll. Auf zerbit.de halte ich es so, dass in der ersten Zeile der komplette Name der Datei abgebildet wird und in einer zweiten die Größe der Datei, sowie eine knappe Beschreibung des Pakets.

Beispiel für OutlookSignature:

<a style="font-weight:bold"
   href="~/download/outlooksignature1704.zip">outlooksignature1704.zip</a>
<br />85 KB - Programm mit Beispielen

Mit diesen zwei Zeilen erstellen wir ein neues UserControl namens DownloadLink.ascx, das folgendes Markup besitzt:

<%@ Control
    Language="VB"
    AutoEventWireup="false"
    CodeFile="DownloadLink.ascx.vb"
    Inherits="controls_DownloadLink" %>

<a style="font-weight:bold"
   href="<%=pstcDownloadFile.Path%>"><%=pstcDownloadFile.Caption%></a>
<br /><%=pstcDownloadFile.Size%> - <%=pstcDownloadFile.Remark%>

Anstelle des HREF-Attributs und des Inhaltes des HTML-Links, sowie der zweiten Zeile, ist etwas Inline-Code getreten, der die Werte einer Struktur namens pstcDownloadFile abruft. Diese Structure ist an erster Stelle im Code-Behind deklariert und beinhaltet alle notwendigen Informationen:

Structure DownloadFileStructure
	Dim Name As String
	Dim Path As String
	Dim Caption As String
	Dim Size As String
	Dim MajorVersion As Integer
    Dim MinorVersion As Integer
	Dim Release As Integer
	Dim Remark As String
End Structure

Public pstcDownloadFile As New DownloadFileStructure

Um die Struktur befüllen zu können muss nun zunächst einmal definiert werden welche Eigenschaften das Control bekommen soll:

Eigenschaft Beschreibung Variable im Code
DownloadPath Pfad zum Download-Ordner aus dem der Download herausgesucht werden soll _strDownloadPath
FilePattern Muster der Download-Datei _strFilePattern
Caption Alternativer Inhalt des Links, wenn nicht der Dateiname verwendet werden soll: _strCaption
Remark Kurze Beschreibung des Pakets _strRemark

Für diese Eigenschaften werden Zugriffsmodifizierer in der Code-Behind-Datei erzeugt, die ich mir hier jetzt mal erspare. Im Download des UserControls weiter unten sind sie natürlich vorhanden.

Das Muster der Download-Datei ist die entscheidende Eigenschaft, denn über sie wird festgelegt nach was im Download-Ordner gesucht werden soll. Da sich die aufeinanderfolgenden Versionspakete in Ihrer Benennung nur durch in der Angabe der Versionsnummer unterscheiden, kann man diese durch einen Platzhalter ersetzen.

So wird zum Beispiel aus:

outlooksignature1704.zip

folgendes Muster:

outlooksignature|xyzz|.zip

Die beiden Pipes begrenzen den auszutauschenden Teil des Dateinamens und die einzelnen Teile der Version werden wie folgt ersetzt:

Platzhalter Beschreibung
x Major-Version
y Minor-Version
z Release/Build

  • Wichtig bei der Benennung der Download-Dateien ist immer das Muster einzuhalten, d.h. ist, wie in diesem Beispiel, das Release zweistellig angegeben, muss bei einem einstelligen Release eine führende Null vorhanden sein.

Mit diesen Informationen ausgestattet, kommen wir nun zur Methode GetActualDownloadFileName, die den aktuellsten Download aus dem angegebenen Order herauspickt und die Struktur pstcDownloadFile befüllt.

Protected Sub GetActualDownloadFileName()

	'Pattern splitten und Index des ersten Begrenzers merken
	Dim arrPattern() As String = _strFilePattern.Split(New [Char]() {"|"c})
	Dim intIndexLeft As Integer = _strFilePattern.IndexOf("|")

	'Such-Pattern für FileInfo erstellen
	Dim stbSearchPattern As New StringBuilder(arrPattern(1))
	stbSearchPattern.Replace("x", "?")
	stbSearchPattern.Replace("y", "?")
	stbSearchPattern.Replace("z", "?")
	Dim strSearchPattern As String = _
		arrPattern(0) & stbSearchPattern.ToString & arrPattern(2)

	'FileInfo initialisieren und Suche durchführen
	Dim objDir As DirectoryInfo = _
		New DirectoryInfo(HttpContext.Current.Server.MapPath(_strDownloadPath))
	Dim objFiles As FileInfo() = _
		objDir.GetFiles(strSearchPattern, SearchOption.TopDirectoryOnly)

	'Mit Such-Pattern Vergleichs-Pattern erzeugen
	Dim strCompareVersion As String = stbSearchPattern.ToString.Replace("?", "0")

	Dim intFoundFile As Integer = 0
	Dim strFileVersion As String = ""

	'Ergebnis durchlaufen und Dateien anhand des Versionsstrings vergleichen
	If objFiles.Length > 0 Then
		For i As Integer = 0 To objFiles.Length - 1

			'Versionsinformation aus Dateinamen extrahieren
			strFileVersion = _
				objFiles(i).Name.Substring(intIndexLeft, strCompareVersion.Length)

			'Pattern mit String.Comparer lexikalisch vergleichen
			If String.Compare(strFileVersion, strCompareVersion) > 0 Then
				strCompareVersion = strFileVersion 'Vergleichspattern neu setzen
				intFoundFile = i 'Index merken
			End If

		Next

		'Name der Datei in Struktur ablegen
		pstcDownloadFile.Name = objFiles(intFoundFile).Name

		'Größe der Datei in KiloByte in Struktur ablegen
		pstcDownloadFile.Size = _
			Format(objFiles(intFoundFile).Length / 1024, "#,##0") & " KB"

		'Versionsinformationen ermitteln und in Struktur ablegen
		Dim strVersionPattern As String = _
			_strFilePattern.Substring(intIndexLeft, strCompareVersion.Length)

		Dim intMajorStart As Integer = strVersionPattern.IndexOf("x") - 1
		Dim intMinorStart As Integer = strVersionPattern.IndexOf("y") - 1
		Dim intReleaseStart As Integer = strVersionPattern.IndexOf("z") - 1

		pstcDownloadFile.MajorVersion = strFileVersion.Substring( _
			intMajorStart, intMinorStart - intMajorStart)
		pstcDownloadFile.MinorVersion = strFileVersion.Substring( _
			intMinorStart, intReleaseStart - intMinorStart)
		pstcDownloadFile.Release = strFileVersion.Substring( _
			intReleaseStart, strCompareVersion.Length - intReleaseStart)

	End If

End Sub

Die Methode erzeugt aus dem Muster zunächst ein Such-Pattern, mit dem alle in Frage kommenden Dateien im Download-Ordner ermittelt werden und vergleicht dann alle Treffer lexikalisch, d.h. anhand der extrahierten Version als Text. Das funktioniert, da zum Beispiel der String "1704" einen höheren Wert hat als "1299". Die Fundstelle des höchsten Wertes wird am Ende herangezogen, um die Dateiinformationen zu extrahieren und in der Struktur abzulegen.

Fehlt nur noch die Initialzündung, sprich das Event, das den Stein innerhalb des Controls ins Rollen bringt:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
	Handles Me.Load

	If _strDownloadPath.Length > 0 And _strFilePattern.Length > 0 Then

		'Aktuellste Datei ermitteln
		Call GetActualDownloadFileName()

		'Dateiziel festlegen
		pstcDownloadFile.Path = _
			ResolveClientUrl(_strDownloadPath) & "/" & pstcDownloadFile.Name

		'Inhalt des Link-Elements
		If _strCaption.Length > 0 Then
			pstcDownloadFile.Caption = _strCaption
		Else
			pstcDownloadFile.Caption = pstcDownloadFile.Name
		End If

		'Dateianmerkung festlegen
		pstcDownloadFile.Remark = _strRemark

	End If

End Sub

Das fertige UserControl kann man nun entweder zentral über die web.config dem Web bekanntmachen...

<add tagPrefix="uct" tagName="DownloadLink"
	src="~/MyControls/DownloadLink.ascx" />

oder es lediglich auf den ASPX-Seiten einbinden auf denen es benötigt wird...

<%@ Register TagPrefix="ucx" TagName="DownloadLink"
	Src="~/MyControls/DownloadLink.ascx" %>

Die Deklaration innerhalb einer ASPX-Seite sieht dann zum Beispiel so aus:

<uct:DownloadLink ID="lnkOutlookSignature" runat="server"
	DownloadPath="~/download"
	FilePattern="outlooksignature|xyzz|.zip"
	Remark="Programm mit Beispielen" />

In meinem Beispiel verwende ich im Markup des Controls nicht alle Werte, die die Struktur zur Verfügung stellt und in der entsprechenden ASPX-Seite auch nicht alle Eigenschaften, aber jeder der dieses UserControl einsetzen möchte, kann sich seinen Download-Link nach eigenem Gusto anpassen.

In Zukunft ist das Deployen einer neuen Version eines Downloads mit einem FTP-Upload getan. Den Rest erledigt ASP.NET.

zum Download...
kick it on dotnet-kicks.de AddThis 0 wikio-Stimme(n) Trackback-Url...

Keine Kommentare bislang...

Dein Kommentar hierzu...


Kommentar-Feed für diesen Beitrag
Gravatare werden unterstützt .:. eMail-Adressen werden nicht veröffentlicht
 

RSS-Feed

Die URL des Standard-Newsfeed von zerbit.de lautet:

http://www.zerbit.de/rssfeed.aspx

Login


 

 

Statistik



kürzlich kommentiert

Artikel 249

  • Datum: 28.01.2008
    Kategorie: ASP.NET
    Zugriffe: 2.070
    Kommentare: 0
    Trackbacks: 0

Letzte Beiträge

Kategorien

Buttons & More

Blog-Roll

Banner Piraten-Partei