Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
által Scott Mitchell
Ez az oktatóanyag bemutatja, hogyan hozhat létre olyan webes felületet, amely lehetővé teszi a felhasználó számára, hogy szöveges adatokat adjon meg és bináris fájlokat töltsön fel. A bináris adatok tárolására rendelkezésre álló lehetőségek szemléltetéséhez az egyik fájl az adatbázisban lesz mentve, míg a másik a fájlrendszerben lesz tárolva.
Bevezetés
Az előző két oktatóanyagban megvizsgáltuk az alkalmazás adatmodelljéhez társított bináris adatok tárolásának technikáit, megvizsgáltuk, hogyan lehet a FileUpload vezérlővel fájlokat küldeni az ügyfélről a webkiszolgálóra, és láttuk, hogyan jeleníthetők meg ezek a bináris adatok egy adat-webvezérlőben. Még nem beszéltünk arról, hogyan társíthatók a feltöltött adatok az adatmodellhez.
Ebben az oktatóanyagban létrehozunk egy weblapot egy új kategória hozzáadásához. A kategória nevéhez és leírásához tartozó Szövegdobozok mellett ennek a lapnak tartalmaznia kell két FileUpload vezérlőt, egyet az új kategória képéhez, egyet pedig a brosúrához. A feltöltött kép közvetlenül az új rekord Picture
oszlopában lesz tárolva, míg a brosúra az ~/Brochures
új rekord BrochurePath
oszlopában mentett fájl elérési útját tartalmazó mappába kerül.
Az új weblap létrehozása előtt frissíteni kell az architektúrát. Az CategoriesTableAdapter
fő lekérdezése nem adja vissza a Picture
oszlopot. Következésképpen az automatikusan létrehozott Insert
metódus csak a , CategoryName
és Description
a BrochurePath
mezők bemeneteit adja meg. Ezért létre kell hoznunk egy további metódust a TableAdapterben, amely mind a négy Categories
mezőt kéri. Az CategoriesBLL
üzleti logikai réteg osztályát is frissíteni kell.
1. lépés: Egy metódus hozzáadásaInsertWithPicture
CategoriesTableAdapter
Amikor az CategoriesTableAdapter
oktatóanyagban létrehoztuk a hátoldalt, úgy konfiguráltuk, hogy automatikusan generáljon INSERT
, UPDATE
és DELETE
utasításokat a fő lekérdezés alapján. Továbbá utasítottuk a TableAdaptert, hogy alkalmazza a DB Direct megközelítést, amely létrehozta a metódusokat Insert
, Update
és Delete
. Ezek a metódusok végrehajtják az automatikusan létrehozott INSERT
, UPDATE
és DELETE
utasításokat, és következésképpen elfogadják a bemeneti paramétereket a fő lekérdezés által visszaadott oszlopok alapján. A Fájlok feltöltése oktatóanyagban bővítettük a CategoriesTableAdapter
fő lekérdezést az BrochurePath
oszlop használatához.
Mivel az CategoriesTableAdapter
s fő lekérdezés nem hivatkozik az Picture
oszlopra, nem adhatunk hozzá új rekordot, és nem frissíthetünk meglévő rekordot az Picture
oszlop értékével. Az információk rögzítéséhez létrehozhatunk egy új metódust a TableAdapterben, amely kifejezetten bináris adatokat tartalmazó rekord beszúrására szolgál, vagy testre szabhatjuk az automatikusan létrehozott utasítást INSERT
. Az automatikusan létrehozott INSERT
utasítás testreszabásával az a probléma, hogy azt kockáztatjuk, hogy a testreszabásokat felülírja a varázsló. Tegyük fel például, hogy az INSERT
utasítást úgy szabtuk testre, hogy az tartalmazza az Picture
oszlop használatát. Ez frissíti a TableAdapter s Insert
metódust, hogy egy további bemeneti paramétert is tartalmazzon a kategória képének bináris adataihoz. Ezután létrehozhatunk egy metódust az üzleti logikai rétegben a DAL metódus használatára, és meghívhatjuk ezt a BLL-metódust a bemutató rétegen keresztül, és minden csodálatosan működik. Vagyis amíg a TableAdapter konfigurációs varázslóval legközelebb nem konfiguráltuk a TableAdaptert. Amint a varázsló befejeződött, az utasítás testreszabása INSERT
felülíródik, a metódus visszaáll a Insert
régi formájára, és a kód már nem fordítható le!
Megjegyzés:
Ez a bosszúság nem jelent problémát, ha tárolt eljárásokat használ az alkalmi SQL-utasítások helyett. Egy jövőbeli oktatóanyag bemutatja a tárolt eljárások használatát az alkalmi SQL-utasítások helyett az adatelérési rétegben.
A lehetséges fejfájás elkerülése érdekében az automatikusan létrehozott SQL-utasítások testreszabása helyett hozzon létre egy új módszert a TableAdapterhez. Ez a névvel ellátott InsertWithPicture
metódus elfogadja a CategoryName
, Description
, BrochurePath
és Picture
oszlopok értékeit, és végrehajt egy utasítást INSERT
, amely mind a négy értéket egy új rekordban tárolja.
Nyissa meg a Gépelt adathalmazt, és a Tervezőben kattintson jobb gombbal az CategoriesTableAdapter
s fejlécre, és válassza a Lekérdezés hozzáadása lehetőséget a helyi menüben. Ezzel elindítja a TableAdapter Lekérdezéskonfiguráció varázslót, amely azzal kezdődik, hogy megkérdezi, hogyan férhet hozzá a TableAdapter-lekérdezés az adatbázishoz. Válassza az SQL-utasítások használata lehetőséget, majd kattintson a Tovább gombra. A következő lépés a létrehozandó lekérdezés típusát kéri. Mivel létrehozunk egy lekérdezést, amely új rekordot ad hozzá a táblához, válassza az INSERT elemet, majd kattintson a Categories
Tovább gombra.
1. ábra: Válassza az INSERT lehetőséget (kattintson ide a teljes méretű kép megtekintéséhez)
Most meg kell adnunk az SQL-utasítást INSERT
. A varázsló automatikusan javasol egy INSERT
, a TableAdapter fő lekérdezésének megfelelő utasítást. Ebben az esetben ez egy INSERT
utasítás, amely beszúrja a CategoryName
, Description
és BrochurePath
az értékeket. Frissítse az utasítást úgy, hogy az Picture
oszlop egy @Picture
paraméterrel együtt szerepeljön, például:
INSERT INTO [Categories]
([CategoryName], [Description], [BrochurePath], [Picture])
VALUES
(@CategoryName, @Description, @BrochurePath, @Picture)
A varázsló utolsó képernyője arra kéri, hogy nevezzük el az új TableAdapter metódust. Adja meg InsertWithPicture
, majd kattintson a Befejezés gombra.
2. ábra: Nevezze el az Új TableAdapter metódust InsertWithPicture
(kattintson ide a teljes méretű kép megtekintéséhez)
2. lépés: Az üzleti logikai réteg frissítése
Mivel a bemutató rétegnek csak az üzleti logikai réteghez kell csatlakoznia ahelyett, hogy megkerülte volna, hogy közvetlenül az adatelérési rétegre lépjen, létre kell hoznunk egy BLL-metódust, amely meghívja az imént létrehozott DAL metódust (InsertWithPicture
). Ebben az oktatóanyagban hozzon létre egy metódust az CategoriesBLL
osztályban a InsertWithPicture
néven, amely három String
-t és egy Byte
tömböt fogad. A String
bemeneti paraméterek a kategória neve, leírása és brosúrafájl elérési útja, míg a Byte
tömb a kategória képének bináris tartalmához tartozik. Ahogy az alábbi kód is mutatja, ez a BLL-metódus meghívja a megfelelő DAL metódust:
<System.ComponentModel.DataObjectMethodAttribute _
(System.ComponentModel.DataObjectMethodType.Insert, False)> _
Public Sub InsertWithPicture(categoryName As String, description As String, _
brochurePath As String, picture() As Byte)
Adapter.InsertWithPicture(categoryName, description, brochurePath, picture)
End Sub
Megjegyzés:
Mielőtt hozzáadja a InsertWithPicture
metódust a BLL-hez, győződjön meg arról, hogy mentette a Gépelt Adatkészletet. Mivel az CategoriesTableAdapter
osztálykód automatikusan jön létre a Gépelt adatkészlet alapján, ha nem menti először a módosításokat a Gépelt adathalmazba, a Adapter
tulajdonság nem fog tudni a InsertWithPicture
metódusról.
3. lépés: A meglévő kategóriák és azok bináris adatainak felsorolása
Ebben az oktatóanyagban létrehozunk egy oldalt, amely lehetővé teszi a végfelhasználó számára, hogy új kategóriát adjon hozzá a rendszerhez, és képet és brosúrát biztosít az új kategóriához. Az előző oktatóanyagban egy GridView-t használtunk egy TemplateField és ImageField használatával az egyes kategóriák nevének, leírásának, képének és hivatkozásának megjelenítéséhez a brosúra letöltéséhez. Replikáljuk ezt a funkciót ebben az oktatóanyagban, és hozzunk létre egy lapot, amely felsorolja az összes meglévő kategóriát, és lehetővé teszi az újak létrehozását.
Először nyissa meg a DisplayOrDownload.aspx
lapot a BinaryData
mappából. Lépjen a Forrás nézetre, és másolja a GridView és az ObjectDataSource deklaratív szintaxisát, majd illessze be a <asp:Content>
elembe UploadInDetailsView.aspx
. Emellett ne felejtse el átmásolni a GenerateBrochureLink
metódust a háttérkód fájlból a DisplayOrDownload.aspx
-be.
3. ábra: Másolja és illessze be a deklaratív szintaxist a fájlba DisplayOrDownload.aspx
UploadInDetailsView.aspx
(kattintson ide a teljes méretű kép megtekintéséhez)
Miután átmásolta a deklaratív szintaxist és GenerateBrochureLink
metódust a UploadInDetailsView.aspx
lapra, tekintse meg a lapot egy böngészőben, hogy minden megfelelően legyen átmásolva. Látnia kell egy GridView-t, amely felsorolja a nyolc kategóriát, amely tartalmazza a brosúra letöltésére mutató hivatkozást, valamint a kategória képét.
4. ábra: Mostantól minden kategóriát látnia kell a bináris adatokkal együtt (ide kattintva megtekintheti a teljes méretű képet)
4. lépés: A beszúrás támogatásának konfigurálásaCategoriesDataSource
A CategoriesDataSource
GridView által Categories
használt ObjectDataSource jelenleg nem teszi lehetővé az adatok beszúrását. Annak érdekében, hogy támogassuk a beszúrást ezen adatforrás-vezérlőn keresztül, összekapcsolnunk kell annak Insert
metódusát a mögöttes objektum egy másik metódusával, CategoriesBLL
. Különösen az általunk a 2. lépésben hozzáadott CategoriesBLL
metódushoz szeretnénk hozzárendelni InsertWithPicture
.
Első lépésként kattintson az ObjectDataSource intelligens címkéjének Adatforrás konfigurálása hivatkozására. Az első képernyőn látható az az objektum, amellyel az adatforrás konfigurálva van, hogy működjön. CategoriesBLL
Hagyja meg ezt a beállítást as-is, és a Tovább gombra kattintva lépjen tovább az Adatmetelyek definiálása képernyőre. Lépjen a BESZÚRÁS lapra, és válassza ki a InsertWithPicture
metódust a legördülő listából. A varázsló befejezéséhez kattintson a Befejezés gombra.
5. ábra: Az ObjectDataSource konfigurálása a InsertWithPicture
metódus használatára (kattintson ide a teljes méretű kép megtekintéséhez)
Megjegyzés:
A varázsló elvégzése után a Visual Studio megkérdezheti, hogy szeretné-e frissíteni a mezőket és kulcsokat, ami újragenerálja az adat webes vezérlőinek mezőit. Válassza a Nem lehetőséget, mert az Igen választás felülírja az esetlegesen végrehajtott mezők testreszabását.
A varázsló befejezése után az ObjectDataSource mostantól tartalmazni fog egy értéket a InsertMethod
tulajdonságához, valamint InsertParameters
a négy kategóriaoszlophoz, ahogy az alábbi deklaratív jelölés szemlélteti:
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories"
TypeName="CategoriesBLL" InsertMethod="InsertWithPicture">
<InsertParameters>
<asp:Parameter Name="categoryName" Type="String" />
<asp:Parameter Name="description" Type="String" />
<asp:Parameter Name="brochurePath" Type="String" />
<asp:Parameter Name="picture" Type="Object" />
</InsertParameters>
</asp:ObjectDataSource>
5. lépés: A beszúrási felület létrehozása
Az Adatok beszúrásának, frissítésének és törlésének áttekintése című cikk első része szerint a DetailsView vezérlő egy beépített beszúrási felületet biztosít, amely a beszúrást támogató adatforrás-vezérlők használatakor használható. Adjunk hozzá egy DetailsView-vezérlőt ehhez a laphoz a GridView fölött, amely véglegesen megjeleníti a beszúrási felületet, így a felhasználó gyorsan hozzáadhat egy új kategóriát. Ha új kategóriát ad hozzá a DetailsView-ban, az alatta lévő GridView automatikusan frissíti és megjeleníti az új kategóriát.
Kezdje azzal, hogy húz egy DetailsView elemet az Eszközkészletből a Tervezőre a GridView fölé, törölje a ID
és NewCategory
tulajdonságok értékeit, majd állítsa be a Height
tulajdonságot Width
értékre. A DetailsView intelligens címkéje alapján kösse hozzá a meglévőhöz CategoriesDataSource
, majd jelölje be a Beszúrás engedélyezése jelölőnégyzetet.
6. ábra: A DetailsView kötése a CategoriesDataSource
beszúráshoz és a beszúrás engedélyezése (kattintson ide a teljes méretű kép megtekintéséhez)
Ha véglegesen meg szeretné jeleníteni a DetailsView-t a beszúrási felületen, állítsa a tulajdonságát DefaultMode
a következőre Insert
: .
Vegye figyelembe, hogy a DetailsView öt BoundField-et tartalmaz: CategoryID
, CategoryName
, Description
, NumberOfProducts
és BrochurePath
, bár a CategoryID
BoundField nem jelenik meg a beszúrási felületen, mert a InsertVisible
tulajdonsága False
értékre van állítva. Ezek a BoundField azért létezik, mert az oszlopokat a GetCategories()
metódus adja vissza, amelyet az ObjectDataSource meghív az adatok lekéréséhez. A beszúráshoz azonban nem szeretnénk engedélyezni, hogy a felhasználó megadjon egy értéket.NumberOfProducts
Ezenkívül lehetővé kell tenni számukra az új kategória képének feltöltését, valamint a brosúra PDF-fájljának feltöltését.
Távolítsa el a NumberOfProducts
BoundFieldet a DetailsView-ból, majd frissítse a HeaderText
és CategoryName
BoundFieldek tulajdonságait Kategória, illetve Brosúra értékre. Ezután alakítsa át a BrochurePath
BoundFieldet sablonmezővé, és adjon hozzá egy új TemplateFieldet a képhez, így az új TemplateField HeaderText
értéke Kép lesz. Helyezze át a Picture
TemplateFieldet úgy, hogy a TemplateField és a BrochurePath
CommandField között legyen.
7. ábra: Kösse a DetailsView-t a CategoriesDataSource
-hoz, és engedélyezze a beszúrást
Ha a BrochurePath
BoundFieldet sablonmezővé alakította a Mezők szerkesztése párbeszédpanelen keresztül, a Sablonmező tartalmaz egy ItemTemplate
, EditItemTemplate
és InsertItemTemplate
. Azonban csak a InsertItemTemplate
szükséges elemekre van szükség, ezért nyugodtan távolítsa el a másik két sablont. Ezen a ponton a DetailsView deklaratív szintaxisának a következőképpen kell kinéznie:
<asp:DetailsView ID="NewCategory" runat="server" AutoGenerateRows="False"
DataKeyNames="CategoryID" DataSourceID="CategoriesDataSource"
DefaultMode="Insert">
<Fields>
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
InsertVisible="False" ReadOnly="True"
SortExpression="CategoryID" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
SortExpression="CategoryName" />
<asp:BoundField DataField="Description" HeaderText="Description"
SortExpression="Description" />
<asp:TemplateField HeaderText="Brochure" SortExpression="BrochurePath">
<InsertItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"
Text='<%# Bind("BrochurePath") %>'></asp:TextBox>
</InsertItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Picture"></asp:TemplateField>
<asp:CommandField ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
FileUpload vezérlők hozzáadása a brosúrához és a képmezőkhöz
A BrochurePath
TemplateField InsertItemTemplate
jelenleg szövegmezőt tartalmaz, míg a Picture
TemplateField nem tartalmaz sablonokat. A FileUpload vezérlők használatához frissíteni kell ezt a két TemplateField-vezérlőt InsertItemTemplate
.
A DetailsView intelligens címkén válassza a Sablonok szerkesztése lehetőséget, majd válassza ki a BrochurePath
TemplateField s InsertItemTemplate
elemet a legördülő listából. Távolítsa el a TextBoxot, majd húzza a FileUpload vezérlőt az eszközkészletből a sablonba. A FileUpload vezérlő s ID
értékének beállítása a következőre BrochureUpload
: . Hasonlóképpen, adjon hozzá egy FileUpload vezérlőt a Picture
TemplateField s InsertItemTemplate
. Állítsd be a FileUpload vezérlőt ID
értékre PictureUpload
.
8. ábra: Fájlbetöltési vezérlő hozzáadása a InsertItemTemplate
fájlhoz (kattintson ide a teljes méretű kép megtekintéséhez)
A kiegészítések elvégzése után a TemplateField két deklaratív szintaxisa a következő lesz:
<asp:TemplateField HeaderText="Brochure" SortExpression="BrochurePath">
<InsertItemTemplate>
<asp:FileUpload ID="BrochureUpload" runat="server" />
</InsertItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Picture">
<InsertItemTemplate>
<asp:FileUpload ID="PictureUpload" runat="server" />
</InsertItemTemplate>
</asp:TemplateField>
Amikor egy felhasználó új kategóriát ad hozzá, biztosítani szeretnénk, hogy a brosúra és a kép a megfelelő fájltípusú legyen. A brosúrához a felhasználónak PDF-fájlt kell megadnia. A képhez a felhasználónak fel kell töltenie egy képfájlt, de engedélyezünk-e bármilyen képfájlt vagy csak egy adott típusú képfájlt, például GIF-eket vagy JPG-ket? A különböző fájltípusok engedélyezéséhez ki kell terjesztenünk a Categories
sémát egy olyan oszlopra, amely rögzíti a fájltípust, hogy ezt a típust elküldhessük az ügyfélnek Response.ContentType
keresztül DisplayCategoryPicture.aspx
. Mivel nincs ilyen oszlopunk, célszerű korlátozni a felhasználókat, hogy csak egy adott képfájltípust adjanak meg. A Categories
táblázat meglévő lemezképei bitképek, a JPG-k azonban a webes képekhez megfelelőbb fájlformátumot jelentenek.
Ha egy felhasználó helytelen fájltípust tölt fel, le kell szakítanunk a beszúrást, és meg kell jeleníteni a problémát jelző üzenetet. Vegyen fel egy Címke web vezérlőelemet a DetailsView alatt. Állítsa be a tulajdonságát ID
a következőre UploadWarning
, törölje a tulajdonságát Text
, állítsa a CssClass
tulajdonságot Figyelmeztetés értékre, a Visible
tulajdonságokat pedig EnableViewState
a következőre False
. A Warning
CSS-osztály a Styles.css
van definiálva, és nagy, piros, dőlt, félkövér betűvel jeleníti meg a szöveget.
Megjegyzés:
Ideális esetben a CategoryName
és Description
BoundFields sablonmezőkké lennének átalakítva, és a beszúrási felületeik testre lennének szabva. A Description
beszúrási felület például valószínűleg jobban megfelelne egy többsoros szövegdoboznak. Mivel az CategoryName
oszlop nem fogad el NULL
értékeket, hozzá kell adni egy RequiredFieldValidatort, hogy a felhasználó értéket adjon az új kategória nevének. Ezek a lépések gyakorlatként maradnak az olvasó számára. Az adatmódosítási felület testreszabásával kapcsolatos részletes áttekintésért tekintse meg az adatmódosítási felületek bővítését.
6. lépés: A feltöltött brosúra mentése a webkiszolgáló fájlrendszerére
Amikor a felhasználó beírja egy új kategória értékeit, és a Beszúrás gombra kattint, visszalépés történik, és a beszúrási munkafolyamat megnyílik. Először a DetailsView eseménye aktiválódikItemInserting
. Ezután a rendszer meghívja Insert()
az ObjectDataSource metódust, amely egy új rekord hozzáadását eredményezi a Categories
táblához. Ezután a DetailsView eseményeItemInserted
aktiválódik.
Az ObjectDataSource metódus meghívása Insert()
előtt először meg kell győződnünk arról, hogy a felhasználó feltöltötte a megfelelő fájltípusokat, majd mentse a brosúra PDF-fájlját a webkiszolgáló fájlrendszerére. Hozzon létre egy eseménykezelőt a DetailsView eseményéhez ItemInserting
, és adja hozzá a következő kódot:
' Reference the FileUpload controls
Dim BrochureUpload As FileUpload = _
CType(NewCategory.FindControl("BrochureUpload"), FileUpload)
If BrochureUpload.HasFile Then
' Make sure that a PDF has been uploaded
If String.Compare(System.IO.Path.GetExtension _
(BrochureUpload.FileName), ".pdf", True) <> 0 Then
UploadWarning.Text = _
"Only PDF documents may be used for a category's brochure."
UploadWarning.Visible = True
e.Cancel = True
Exit Sub
End If
End If
Az eseménykezelő először a BrochureUpload
FileUpload vezérlőre hivatkozik a DetailsView-sablonokból. Ezután, ha feltöltöttek egy brosúrát, a rendszer megvizsgálja a feltöltött fájl bővítményét. Ha a bővítmény nem .PDF, figyelmeztetés jelenik meg, a beszúrás megszakad, és az eseménykezelő végrehajtása véget ér.
Megjegyzés:
A feltöltött fájl kiterjesztésére való támaszkodás nem biztos módszer annak biztosítására, hogy a feltöltött fájl PDF-dokumentum legyen. A felhasználó rendelkezhet érvényes PDF-dokumentummal a kiterjesztéssel .Brochure
, vagy készíthetett egy nem PDF formátumú dokumentumot, és mellékelhette .pdf
. A fájl bináris tartalmát programozott módon kell megvizsgálni a fájltípus egyértelműbb ellenőrzéséhez. Az ilyen alapos megközelítések azonban gyakran túlzások; a bővítmény ellenőrzése a legtöbb forgatókönyv esetében elegendő.
A Fájlok feltöltése oktatóanyagban leírtaknak megfelelően ügyelni kell a fájlok fájlrendszerbe való mentésekor, hogy az egyik felhasználó feltöltése ne írja felül a másikat. Ebben az oktatóanyagban megpróbáljuk ugyanazt a nevet használni, mint a feltöltött fájl. Ha már létezik ilyen nevű fájl a ~/Brochures
könyvtárban, a végén hozzáfűzünk egy számot, amíg egyedi név nem található. Ha például a felhasználó feltölt egy brosúrafájlt, Meats.pdf
de már van egy fájl neve Meats.pdf
a ~/Brochures
mappában, a mentett fájl nevét a következőre Meats-1.pdf
módosítjuk. Ha ez létezik, megpróbáljuk Meats-2.pdf
, és így tovább, amíg nem talál egy egyedi fájlnevet.
Az alábbi kód a File.Exists(path)
metódus használatával állapítja meg, hogy létezik-e már fájl a megadott fájlnévvel. Ha igen, addig próbálkozik a brosúra új fájlnevekkel, amíg nem talál ütközést.
Const BrochureDirectory As String = "~/Brochures/"
Dim brochurePath As String = BrochureDirectory & BrochureUpload.FileName
Dim fileNameWithoutExtension As String = _
System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName)
Dim iteration As Integer = 1
While System.IO.File.Exists(Server.MapPath(brochurePath))
brochurePath = String.Concat(BrochureDirectory, _
fileNameWithoutExtension, "-", iteration, ".pdf")
iteration += 1
End While
Az érvényes fájlnév megtalálása után a fájlt a fájlrendszerbe kell menteni, és frissíteni kell az ObjectDataSource brochurePath``InsertParameter
értékét, hogy a fájlnév bekerüljön az adatbázisba. Ahogy a Fájlok feltöltése oktatóanyagban is láttuk, a fájl menthető a FileUpload vezérlő s SaveAs(path)
metódusával. Az ObjectDataSource brochurePath
paraméter frissítéséhez használja a e.Values
gyűjteményt.
' Save the file to disk and set the value of the brochurePath parameter
BrochureUpload.SaveAs(Server.MapPath(brochurePath))
e.Values("brochurePath") = brochurePath
7. lépés: A feltöltött kép mentése az adatbázisba
A feltöltött kép új Categories
rekordban való tárolásához a feltöltött bináris tartalmat hozzá kell rendelnünk az ObjectDataSource paraméteréhez picture
a DetailsView eseményben ItemInserting
. A feladat végrehajtása előtt azonban először meg kell győződnünk arról, hogy a feltöltött kép JPG formátumú, nem pedig más képtípus. A 6. lépéshez hasonlóan használjuk a feltöltött kép fájlkiterjesztését annak típusának megállapításához.
Bár a Categories
táblázat lehetővé teszi a NULL
oszlopban lévő Picture
értékeket, jelenleg az összes kategória rendelkezik képpel. Kényszerítsük a felhasználót arra, hogy adjon meg egy képet, amikor új kategóriát ad hozzá ezen a lapon. Az alábbi kód ellenőrzi, hogy egy kép feltöltése megtörtént-e, és hogy megfelelő kiterjesztéssel rendelkezik-e.
' Reference the FileUpload controls
Dim PictureUpload As FileUpload = _
CType(NewCategory.FindControl("PictureUpload"), FileUpload)
If PictureUpload.HasFile Then
' Make sure that a JPG has been uploaded
If String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), _
".jpg", True) <> 0 AndAlso _
String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), _
".jpeg", True) <> 0 Then
UploadWarning.Text = _
"Only JPG documents may be used for a category's picture."
UploadWarning.Visible = True
e.Cancel = True
Exit Sub
End If
Else
' No picture uploaded!
UploadWarning.Text = _
"You must provide a picture for the new category."
UploadWarning.Visible = True
e.Cancel = True
Exit Sub
End If
Ezt a kódot a 6. lépésben kell elhelyezni a kód elé , hogy ha probléma merül fel a képfeltöltéssel kapcsolatban, az eseménykezelő leáll, mielőtt a brosúrafájlt a fájlrendszerbe mentené.
Feltételezve, hogy a megfelelő fájl feltöltése megtörtént, rendelje hozzá a feltöltött bináris tartalmat a képparaméter s értékéhez a következő kódsor használatával:
' Set the value of the picture parameter
e.Values("picture") = PictureUpload.FileBytes
A TeljesItemInserting
eseménykezelő
A teljesség kedvéért itt található az ItemInserting
-eseménykezelő teljes terjedelmében:
Protected Sub NewCategory_ItemInserting _
(sender As Object, e As DetailsViewInsertEventArgs) _
Handles NewCategory.ItemInserting
' Reference the FileUpload controls
Dim PictureUpload As FileUpload = _
CType(NewCategory.FindControl("PictureUpload"), FileUpload)
If PictureUpload.HasFile Then
' Make sure that a JPG has been uploaded
If String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), _
".jpg", True) <> 0 AndAlso _
String.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), _
".jpeg", True) <> 0 Then
UploadWarning.Text = _
"Only JPG documents may be used for a category's picture."
UploadWarning.Visible = True
e.Cancel = True
Exit Sub
End If
Else
' No picture uploaded!
UploadWarning.Text = _
"You must provide a picture for the new category."
UploadWarning.Visible = True
e.Cancel = True
Exit Sub
End If
' Set the value of the picture parameter
e.Values("picture") = PictureUpload.FileBytes
' Reference the FileUpload controls
Dim BrochureUpload As FileUpload = _
CType(NewCategory.FindControl("BrochureUpload"), FileUpload)
If BrochureUpload.HasFile Then
' Make sure that a PDF has been uploaded
If String.Compare(System.IO.Path.GetExtension(BrochureUpload.FileName), _
".pdf", True) <> 0 Then
UploadWarning.Text = _
"Only PDF documents may be used for a category's brochure."
UploadWarning.Visible = True
e.Cancel = True
Exit Sub
End If
Const BrochureDirectory As String = "~/Brochures/"
Dim brochurePath As String = BrochureDirectory & BrochureUpload.FileName
Dim fileNameWithoutExtension As String = _
System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName)
Dim iteration As Integer = 1
While System.IO.File.Exists(Server.MapPath(brochurePath))
brochurePath = String.Concat(BrochureDirectory, _
fileNameWithoutExtension, "-", iteration, ".pdf")
iteration += 1
End While
' Save the file to disk and set the value of the brochurePath parameter
BrochureUpload.SaveAs(Server.MapPath(brochurePath))
e.Values("brochurePath") = brochurePath
End If
End Sub
8. lépés: AzDisplayCategoryPicture.aspx
oldal javítása
Szánjunk egy kis időt a beszúrási felület és ItemInserting
az eseménykezelő tesztelésére, amely az elmúlt néhány lépésben jött létre. Látogasson el a UploadInDetailsView.aspx
lapra egy böngészőben, és próbáljon meg hozzáadni egy kategóriát, de hagyja ki a képet, vagy adjon meg egy nem JPG formátumú képet vagy egy nem PDF-brosúrát. Ezen esetek bármelyikében megjelenik egy hibaüzenet, és a beszúrási munkafolyamat megszakad.
9. ábra: Érvénytelen fájltípus feltöltése esetén figyelmeztető üzenet jelenik meg (ide kattintva megtekintheti a teljes méretű képet)
Miután meggyőződött arról, hogy a laphoz fel kell tölteni egy képet, és nem fogad el nem PDF vagy nem JPG formátumú fájlokat, adjon hozzá egy új kategóriát érvényes JPG-képpel, és hagyja üresen a Brosúra mezőt. Miután a Beszúrás gombra kattintott, a lap visszakerül, és egy új rekordot ad hozzá a Categories
táblázathoz, amelyben a feltöltött kép bináris tartalma közvetlenül az adatbázisban van tárolva. A GridView frissül, és megjeleníti az újonnan hozzáadott kategória sorát, de ahogy a 10. ábrán látható, az új kategória képe nem jelenik meg megfelelően.
10. ábra: Az Új kategória képe nem jelenik meg (kattintson ide a teljes méretű kép megtekintéséhez)
Az új kép azért nem jelenik meg, mert a DisplayCategoryPicture.aspx
megadott kategóriaképet visszaadó lap úgy van konfigurálva, hogy feldolgozhassa az OLE fejlécet tartalmazó bitképeket. Ezt a 78 bájtos fejlécet a rendszer eltávolítja az Picture
oszlop bináris tartalmából, mielőtt visszaküldené őket az ügyfélnek. Az új kategóriához most feltöltött JPG-fájl azonban nem rendelkezik ezzel az OLE fejléccel; ezért a rendszer eltávolítja az érvényes, szükséges bájtokat a kép bináris adataiból.
Mivel a táblázatban most már mind az OLE-fejléceket, mind a JPG-ket tartalmazó bitképek találhatók, frissítenünk kell Categories
-t, hogy az eltávolítsa az OLE fejlécet az eredeti nyolc kategóriánál, és mellőzze ezt az eltávolítást az újabb kategóriarekordoknál. A következő oktatóanyagban megvizsgáljuk, hogyan frissíthet egy meglévő rekord képét, és frissítjük az összes régi kategóriaképet, hogy azok JPG-k legyenek. Egyelőre azonban az alábbi kóddal DisplayCategoryPicture.aspx
távolítsa el az OLE-fejléceket, csak az eredeti nyolc kategóriára korlátozva:
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim categoryID As Integer = Convert.ToInt32(Request.QueryString("CategoryID"))
' Get information about the specified category
Dim categoryAPI As New CategoriesBLL()
Dim categories As Northwind.CategoriesDataTable = _
categoryAPI.GetCategoryWithBinaryDataByCategoryID(categoryID)
Dim category As Northwind.CategoriesRow = categories(0)
If categoryID <= 8 Then
' Output HTTP headers providing information about the binary data
Response.ContentType = "image/bmp"
' Output the binary data
' But first we need to strip out the OLE header
Const OleHeaderLength As Integer = 78
Dim strippedImageLength As Integer = _
category.Picture.Length - OleHeaderLength
Dim strippedImageData(strippedImageLength) As Byte
Array.Copy(category.Picture, OleHeaderLength, _
strippedImageData, 0, strippedImageLength)
Response.BinaryWrite(strippedImageData)
Else
' For new categories, images are JPGs...
' Output HTTP headers providing information about the binary data
Response.ContentType = "image/jpeg"
' Output the binary data
Response.BinaryWrite(category.Picture)
End If
End Sub
Ezzel a módosítással a JPG-rendszerkép helyesen jelenik meg a GridView-ban.
11. ábra: Az új kategóriák JPG-képei megfelelően renderelve vannak (ide kattintva megtekintheti a teljes méretű képet)
9. lépés: A brosúra törlése kivétel esetén
A bináris adatok webkiszolgáló fájlrendszeren való tárolásának egyik kihívása, hogy leválasztja az adatmodellt és a bináris adatokat. Ezért egy rekord törlésekor a fájlrendszer megfelelő bináris adatait is el kell távolítani. Ez a beszúráskor is szerepet játszhat. Fontolja meg a következő forgatókönyvet: a felhasználó új kategóriát ad hozzá, megjelölve egy megfelelő képet és brosúrát. Amikor a Beszúrás gombra kattint, postback történik, és a DetailsView ItemInserting
esemény aktiválódik, amely a brosúrát a webkiszolgáló fájlrendszerére menti. Ezután az ObjectDataSource Insert()
metódusa kerül meghívásra, amely meghívja az CategoriesBLL
osztály InsertWithPicture
metódusát, amely meghívja a CategoriesTableAdapter
osztály InsertWithPicture
metódusát.
Mi történik, ha az adatbázis offline állapotban van, vagy ha az SQL-utasítás hibát INSERT
jelez? Nyilvánvaló, hogy az INSERT sikertelen lesz, ezért a program nem ad hozzá új kategóriasort az adatbázishoz. De a feltöltött brosúrafájl továbbra is a webkiszolgáló fájlrendszerén található! Ezt a fájlt kivétel miatt törölni kell a beszúrási munkafolyamat során.
A BLL- és DAL-Level-kivételek kezelése egy ASP.NET-lap oktatóanyagában már korábban megvitatottak szerint, amikor egy kivételt az architektúra mélyebb részéből dobnak ki, az felfelé halad a különböző rétegeken keresztül. A Bemutató rétegben megállapíthatjuk, hogy történt-e kivétel a DetailsView eseményéből ItemInserted
. Ez az eseménykezelő az ObjectDataSource-ok InsertParameters
értékeit is biztosítja. Ezért létrehozhatunk egy eseménykezelőt az ItemInserted
eseményhez, amely ellenőrzi, hogy volt-e kivétel, és ha igen, törli az ObjectDataSource brochurePath
paraméter által megadott fájlt:
Protected Sub NewCategory_ItemInserted _
(sender As Object, e As DetailsViewInsertedEventArgs) _
Handles NewCategory.ItemInserted
If e.Exception IsNot Nothing Then
' Need to delete brochure file, if it exists
If e.Values("brochurePath") IsNot Nothing Then
System.IO.File.Delete(Server.MapPath _
(e.Values("brochurePath").ToString()))
End If
End If
End Sub
Összefoglalás
Számos lépést kell végrehajtani annak érdekében, hogy webes felületet biztosítson a bináris adatokat tartalmazó rekordok hozzáadásához. Ha a bináris adatok közvetlenül az adatbázisba vannak tárolva, valószínűleg frissítenie kell az architektúrát, és adott metódusokat kell hozzáadnia a bináris adatok beszúrási eseteinek kezeléséhez. Az architektúra frissítését követően a következő lépés a beszúrási felület létrehozása, amely egy testre szabott DetailsView használatával valósítható meg, amely minden bináris adatmezőhöz tartalmaz egy FileUpload vezérlőt. A feltöltött adatok ezután menthetők a webkiszolgáló fájlrendszerére, vagy hozzárendelhetők egy adatforrásparaméterhez a DetailsView ItemInserting
eseménykezelőjében.
A bináris adatok fájlrendszerbe való mentése több tervezést igényel, mint az adatok közvetlenül az adatbázisba való mentése. Annak érdekében, hogy egy felhasználó feltöltése ne írjon felül egy másikét, megfelelő elnevezési sémát kell választani. Emellett további lépéseket kell tenni a feltöltött fájl törléséhez, ha az adatbázis beszúrása sikertelen.
Mostantól brosúrával és képpel új kategóriákat adhatunk hozzá a rendszerhez, de még nem foglalkoztunk azzal, hogyan frissíthetjük a meglévő kategória bináris adatait, vagy hogyan távolíthatjuk el helyesen a törölt kategóriák bináris adatait. Ezt a két témakört a következő oktatóanyagban ismertetjük.
Boldog programozást!
Tudnivalók a szerzőről
Scott Mitchell, hét ASP/ASP.NET-könyv szerzője és a 4GuysFromRolla.com alapítója, 1998 óta dolgozik a Microsoft webtechnológiáival. Scott független tanácsadóként, edzőként és íróként dolgozik. Legújabb könyve Sams Tanuld meg ASP.NET 2.0 24 óra alatt. Ő itt elérhető mitchell@4GuysFromRolla.com.
Külön köszönet
Ezt az oktatóanyag-sorozatot sok hasznos véleményező áttekintette. Az oktatóanyag fő véleményezői Dave Gardner, Teresa Murphy és Bernadette Leigh voltak. Szeretné áttekinteni a közelgő MSDN-cikkeimet? Ha igen, írj egy sort a mitchell@4GuysFromRolla.com-ra.