Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
tarafından Scott Mitchell
Bu öğreticide, kullanıcının hem metin verilerini girmesini hem de ikili dosyaları karşıya yüklemesini sağlayan bir Web arabiriminin nasıl oluşturulacağı gösterilmektedir. İkili verileri depolamak için kullanılabilecek seçenekleri göstermek için, bir dosya veritabanına kaydedilirken diğeri dosya sisteminde depolanır.
Giriş
Önceki iki öğreticide, uygulamanın veri modeliyle ilişkili ikili verileri depolama tekniklerini inceledik, istemciden web sunucusuna dosya göndermek için FileUpload denetiminin nasıl kullanılacağını inceledik ve bu ikili verilerin bir veri Web denetiminde nasıl sunıldığını gördük. Ancak karşıya yüklenen verileri veri modeliyle ilişkilendirme hakkında henüz konuşmadık.
Bu öğreticide yeni bir kategori eklemek için bir web sayfası oluşturacağız. Kategorinin adı ve açıklaması için TextBoxes'a ek olarak, bu sayfada biri yeni kategori resmi, diğeri broşür için olmak üzere iki FileUpload denetimi bulunacaktır. Karşıya yüklenen resim doğrudan yeni kaydın Picture
sütununda depolanırken, broşür, dosyanın yolunun yeni kaydın ~/Brochures
sütununa kaydedileceği BrochurePath
klasörüne kaydedilecektir.
Bu yeni web sayfasını oluşturmadan önce mimariyi güncelleştirmemiz gerekir.
CategoriesTableAdapter
ana sorgusu Picture
sütununu getirmez. Sonuç olarak, otomatik oluşturulan Insert
yöntemi yalnızca CategoryName
, Description
ve BrochurePath
alanları için girişlere sahiptir. Bu nedenle, TableAdapter'da dört Categories
alanın tümünü isteyen ek bir yöntem oluşturmamız gerekir.
CategoriesBLL
İş Mantığı Katmanı'ndaki sınıfın da güncelleştirilmiş olması gerekir.
1. Adım:InsertWithPicture
yöntemi eklemeCategoriesTableAdapter
CategoriesTableAdapter
öğreticisinde 'ı oluşturduğumuzda, bunu ana sorguyu temel alarak INSERT
, UPDATE
ve DELETE
deyimlerini otomatik olarak oluşturacak şekilde yapılandırdık. Ayrıca TableAdapter'a, Doğrudan Veritabanı yaklaşımını kullanması talimatını verdik, bu da Insert
, Update
ve Delete
yöntemlerini oluşturdu. Bu yöntemler otomatik olarak oluşturulan INSERT
, UPDATE
ve DELETE
deyimlerini yürütür ve sonuç olarak ana sorgu tarafından döndürülen sütunlara göre giriş parametrelerini kabul eder.
Dosyaları Karşıya Yükleme öğreticisinde ana sorguyu CategoriesTableAdapter
kullanarak BrochurePath
sütununu genişlettik.
CategoriesTableAdapter
ana sorgusu Picture
sütununa başvurmadığından, ne Picture
sütununa yeni bir kayıt ekleyebiliriz ne de mevcut bir kaydı güncelleyebiliriz. Bu bilgileri yakalamak için TableAdapter'da özel olarak ikili veri içeren bir kayıt eklemek için kullanılan yeni bir yöntem oluşturabilir veya otomatik olarak oluşturulan INSERT
deyimi özelleştirebiliriz. Otomatik oluşturulan INSERT
deyimi özelleştirmeyle ilgili sorun, özelleştirmelerimizin sihirbaz tarafından üzerine yazılmasını riske atmamızdır. Örneğin, INSERT
deyimini Picture
sütunun kullanımını içerecek şekilde özelleştirdiğimizi hayal edin. Bu, TableAdapter s Insert
yöntemini kategorinin resminin ikili verileri için ek bir giriş parametresi içerecek şekilde güncelleştirir. Daha sonra İş Mantığı Katmanı'nda bu DAL yöntemini kullanmak ve Sunu Katmanı aracılığıyla bu BLL yöntemini çağırmak için bir yöntem oluşturabiliriz ve her şey harika çalışır. Yani, bir sonraki sefer TableAdapter Yapılandırma Sihirbazı aracılığıyla TableAdapter'ı yapılandırdığımız zamana kadar. Sihirbazı tamamlar tamamlamaz, INSERT
deyimine yaptığımız özelleştirmeler üzerine yazılır, Insert
metodu eski haline geri döner ve kodumuz artık derlenemeyecek duruma gelir!
Uyarı
Bu rahatsızlık, geçici SQL deyimleri yerine saklı yordamlar kullanıldığında söz konusu değildir. Gelecekteki bir öğreticide, Veri Erişim Katmanı'nda geçici SQL deyimleri yerine saklı yordamları kullanmayı inceleyeceğiz.
Bu olası baş ağrısından kaçınmak için otomatik olarak oluşturulan SQL deyimlerini özelleştirmek yerine TableAdapter için yeni bir yöntem oluşturalım.
InsertWithPicture
adlı bu yöntem, CategoryName
, Description
, BrochurePath
ve Picture
sütunları için değerleri kabul eder ve dört değerin tümünü yeni bir kayıtta depolayan bir INSERT
deyimi yürütür.
Yazılmış Veri Kümesi'ni açın ve Tasarımcı'dan CategoriesTableAdapter
üstbilgisine üzerine sağ tıklayın ve açılan menüden Sorgu Ekle'yi seçin. Bu, TableAdapter sorgusunun veritabanına nasıl erişmesi gerektiğini sorarak başlayan TableAdapter Sorgu Yapılandırma Sihirbazı'nı başlatır. SQL deyimlerini kullan'ı seçin ve İleri'ye tıklayın. Sonraki adım, oluşturulacak sorgu türünü ister. Tabloya yeni bir kayıt eklemek için sorgu oluşturduğumuz için Categories
EKLE'yi seçin ve İleri'ye tıklayın.
Şekil 1: INSERT Seçeneğini belirleyin (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Şimdi SQL deyimini INSERT
belirtmemiz gerekiyor. Sihirbaz, TableAdapter ana sorgusuna karşılık gelen bir INSERT
deyimi otomatik olarak önerir. Bu durumda, INSERT
deyim, CategoryName
, Description
ve BrochurePath
değerlerini ekler. Açıklamayı güncelleştirerek Picture
sütunu @Picture
parametreyle birlikte ekleyin, örneğin:
INSERT INTO [Categories]
([CategoryName], [Description], [BrochurePath], [Picture])
VALUES
(@CategoryName, @Description, @BrochurePath, @Picture)
Sihirbazın son ekranı yeni TableAdapter yöntemini adlandırmamızı ister. Girin InsertWithPicture
ve Son'a tıklayın.
Şekil 2: Yeni TableAdapter Yöntemini Adlandırın InsertWithPicture
(Tam boyutlu görüntüyü görüntülemek için tıklayın)
2. Adım: İş Mantığı Katmanını Güncelleştirme
Sunu Katmanı doğrudan Veri Erişim Katmanı'na gitmek için bunu atlamak yerine yalnızca İş Mantığı Katmanı ile arabirim oluşturması gerektiğinden, yeni oluşturduğumuz DAL yöntemini çağıran bir BLL yöntemi oluşturmamız gerekir (InsertWithPicture
). Bu öğretici için CategoriesBLL
sınıfında InsertWithPicture
adlı bir yöntem oluşturun, bu yöntem giriş olarak üç String
ve bir Byte
dizisi kabul eder. Giriş String
parametreleri kategorinin adı, açıklaması ve broşür dosyası yolu için, dizi ise Byte
kategori resminin ikili içeriğine yöneliktir. Aşağıdaki kodda gösterildiği gibi, bu BLL yöntemi ilgili DAL yöntemini çağırır:
<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
Uyarı
Typed DataSet'i BLL'ye InsertWithPicture
yöntemini eklemeden önce kaydettiğinizden emin olun.
CategoriesTableAdapter
Sınıf kodu Typed DataSet'e göre otomatik olarak oluşturulduğundan, değişikliklerinizi önce Typed DataSet'e Adapter
kaydetmezseniz özelliği yöntemi hakkında InsertWithPicture
bilgi sahibi olmaz.
3. Adım: Mevcut Kategorileri ve bunların İkili Verilerini Listeleme
Bu öğreticide, son kullanıcının sisteme yeni bir kategori eklemesine olanak tanıyan ve yeni kategori için bir resim ve broşür sağlayan bir sayfa oluşturacağız. Önceki öğreticide, her kategorinin adını, açıklamasını, resmini ve broşürünü indirmek için bir bağlantıyı görüntülemek için TemplateField ve ImageField içeren bir GridView kullandık. Bu öğreticinin işlevselliğini çoğaltalım ve hem mevcut kategorileri listeleyen hem de yeni kategorilerin oluşturulmasına izin veren bir sayfa oluşturalım.
Öncelikle DisplayOrDownload.aspx
klasöründen BinaryData
sayfasını açarak başlayın. Kaynak görünümüne gidin ve GridView ile ObjectDataSource'un bildirim temelli söz dizimini kopyalayarak <asp:Content>
etiketindeki UploadInDetailsView.aspx
elemanı içine yapıştırın. Ayrıca, GenerateBrochureLink
yöntemini DisplayOrDownload.aspx
kod arkası sınıfından UploadInDetailsView.aspx
öğesine kopyalamayı unutmayın.
Şekil 3: Bildirim Temelli Söz Dizimini 'den DisplayOrDownload.aspx
UploadInDetailsView.aspx
kopyalayıp yapıştırın (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Bildirim temelli söz dizimini ve GenerateBrochureLink
yöntemi sayfaya UploadInDetailsView.aspx
kopyaladıktan sonra, her şeyin doğru şekilde kopyalanmasını sağlamak için sayfayı tarayıcı üzerinden görüntüleyin. Broşürü ve kategori resmini indirme bağlantısını içeren sekiz kategoriyi listeleyen bir GridView görmeniz gerekir.
Şekil 4: Artık Her Kategoriyi İkili Verileriyle Birlikte Görmeniz Gerekir (Tam boyutlu görüntüyü görüntülemek için tıklayın)
4. Adım: Eklemeyi Desteklemek için Yapılandırma
CategoriesDataSource
GridView tarafından kullanılan Categories
ObjectDataSource şu anda veri ekleme olanağı sağlamaz. Bu veri kaynağı denetimi aracılığıyla eklemeyi desteklemek için Insert
yöntemini temel nesnesindeki CategoriesBLL
yöntemine eşlememiz gerekir. Özellikle, CategoriesBLL
. Adım'da geri eklediğimiz InsertWithPicture
yöntemine eşlemek istiyoruz.
ObjectDataSource'un akıllı etiketinden Veri Kaynağını Yapılandır bağlantısına tıklayarak başlayın. İlk ekranda, veri kaynağının çalışmak üzere yapılandırıldığı nesne CategoriesBLL
gösterilir. Bu ayarı as-is bırakın ve İleri'ye tıklayarak Veri Yöntemlerini Tanımla ekranına ilerleyin. INSERT sekmesine gidin ve açılan listeden yöntemini seçin InsertWithPicture
. Sihirbazı tamamlamak için Son'a tıklayın.
Şekil 5: ObjectDataSource'un Yöntemini kullanacak şekilde yapılandırılması InsertWithPicture
(Tam boyutlu görüntüyü görüntülemek için tıklayın)
Uyarı
Sihirbazı tamamladıktan sonra Visual Studio, Veri Web denetimleri alanlarını yeniden oluşturacak olan Alanları ve Anahtarları Yenilemek isteyip istemediğinizi sorabilir. Hayır'ı seçin, çünkü Evet'i seçmek daha önce yaptığınız alan özelleştirmelerinin üzerine yazacaktır.
Sihirbazı tamamladıktan sonra, ObjectDataSource şimdi üzerinde InsertMethod
özelliği için bir değer ve dört kategori sütunu için InsertParameters
olduğu gibi bir değer içerecektir, aşağıdaki bildirim temelli işaretlemede gösterildiği gibi:
<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. Adım: Ekleme Arabirimi Oluşturma
İlk olarak Veri Ekleme, Güncelleştirme ve Silmeye Genel Bakış bölümünde ele alınan DetailsView denetimi, eklemeyi destekleyen bir veri kaynağı denetimiyle çalışırken kullanılabilecek yerleşik bir ekleme arabirimi sağlar. Bu sayfada GridView'un üzerine kalıcı olarak ekleme arabirimini işleyecek bir DetailsView denetimi ekleyelim, böylece kullanıcı hızla yeni bir kategori ekleyebilir. DetailsView'a yeni bir kategori eklendikten sonra, altındaki GridView otomatik olarak yenilenir ve yeni kategoriyi görüntüler.
Tasarımcı'da GridView'un üzerine Toolbox'tan bir DetailsView sürükleyerek başlayın, ardından ID
özelliğini NewCategory
olarak ayarlayın ve Height
ile Width
özellik değerlerini temizleyin. DetailsView akıllı etiketinden mevcut CategoriesDataSource
öğesine bağlayın ve "Ekleme Seçeneğini Etkinleştir" kutusunu işaretleyin.
Şekil 6: DetailsView'ı ve Eklemeyi Etkinleştir'e CategoriesDataSource
bağlama (Tam boyutlu görüntüyü görüntülemek için tıklayın)
DetailsView'i ekleme arabiriminde kalıcı olarak göstermek için DefaultMode
özelliğini Insert
olarak ayarlayın.
Özelliği CategoryID
olarak ayarlandığından, DetailsView'da beş BoundField CategoryName
, Description
, NumberOfProducts
, BrochurePath
ve CategoryID
bulunmasına rağmen, InsertVisible
BoundField ekleme arabiriminde False
olarak işlenmez. Bu BoundField'ler, objectDataSource'un verilerini almak için çağırdığı yöntem tarafından GetCategories()
döndürülen sütunlar olduğundan vardır. Ancak ekleme için kullanıcının için NumberOfProducts
bir değer belirtmesine izin vermek istemiyoruz. Ayrıca, yeni kategori için bir resim yüklemelerine ve broşür için pdf yüklemelerine izin vermemiz gerekir.
NumberOfProducts
BoundField'i DetailsView'dan tamamen kaldırın ve ardından HeaderText
özelliklerini güncelleştirerek CategoryName
ve BrochurePath
BoundField'leri sırasıyla Kategori ve Broşür olarak ayarlayın. Ardından, BoundField'i BrochurePath
TemplateField'e dönüştürün ve resim için yeni bir TemplateField ekleyin ve bu yeni TemplateField'e HeaderText
Resim değeri sağlayın. TemplateField'i Picture
TemplateField ile CommandField arasında BrochurePath
olacak şekilde taşıyın.
Şekil 7: DetailsView'ı CategoriesDataSource
'e bağlama ve Eklemeyi Etkinleştir
Alanları Düzenle iletişim kutusu aracılığıyla BoundField'i TemplateField'e dönüştürdüyseniz BrochurePath
, TemplateField bir ItemTemplate
, EditItemTemplate
ve InsertItemTemplate
içerir. Yalnızca InsertItemTemplate
gereklidir, bu yüzden diğer iki şablonu kaldırabilirsiniz. Bu noktada DetailsView'unuzun bildirim temelli söz dizimi aşağıdaki gibi görünmelidir:
<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>
Broşür ve Resim Alanları için DosyaYükleme Denetimleri Ekleme
Şu anda BrochurePath
TemplateField'ler InsertItemTemplate
bir TextBox içerirken Picture
TemplateField herhangi bir şablon içermez. FileUpload denetimlerini kullanmak için bu iki TemplateField InsertItemTemplate
öğesini güncelleştirmemiz gerekiyor.
DetailsView s akıllı etiketinden Şablonları Düzenle seçeneğini belirleyin ve ardından açılan listeden BrochurePath
TemplateField'ü InsertItemTemplate
seçin. TextBox'ı kaldırın ve ardından Araç Kutusu'ndan bir FileUpload denetimini şablona sürükleyin. FileUpload denetimini ID
olarak BrochureUpload
ayarlayın. Benzer şekilde, TemplateField's Picture
öğesine InsertItemTemplate
bir FileUpload denetimi ekleyin. Bu FileUpload denetimini ID
olarak PictureUpload
ayarlayın.
Şekil 8: Dosyasına DosyaYükleme Denetimi InsertItemTemplate
Ekleme (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Yapılan bu eklemelerden sonra, TemplateField'lerin bildirimsel söz dizimi şöyle olacaktır:
<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>
Kullanıcı yeni bir kategori eklediğinde, broşür ve resmin doğru dosya türünde olduğundan emin olmak istiyoruz. Broşür için kullanıcının bir PDF sağlaması gerekir. Resim için kullanıcının bir görüntü dosyasını karşıya yüklemesine ihtiyacımız var, ancak herhangi bir görüntü dosyasına veya GIF veya JPG gibi belirli bir türdeki görüntü dosyalarına izin mi verdik? Farklı dosya türlerine izin vermek için, Categories
şemasını dosya türünü yakalayan bir sütun ekleyecek şekilde genişletmemiz gerekir, böylece bu tür Response.ContentType
aracılığıyla DisplayCategoryPicture.aspx
içinde istemciye gönderilebilir. Böyle bir sütuna sahip olmadığımıza göre, kullanıcıların yalnızca belirli bir görüntü dosya türü sağlamasını kısıtlamak akıllıca olacaktır. Tablonun Categories
mevcut görüntüleri bit eşlemlerdir, ancak JPG'ler web üzerinden sunulan görüntüler için daha uygun bir dosya biçimidir.
Kullanıcı yanlış bir dosya türünü karşıya yüklerse, ekleme işlemini iptal edip sorunu belirten bir ileti görüntülememiz gerekir. DetailsView'un altına bir Label Web denetimi ekleyin.
ID
özelliğini UploadWarning
olarak ayarlayın, Text
özelliğini temizleyin, CssClass
özelliğini Uyarı olarak ayarlayın ve Visible
ve EnableViewState
özelliklerini False
olarak ayarlayın.
Warning
CSS sınıfı içinde Styles.css
tanımlanır ve metni büyük, kırmızı, italik, kalın yazı tipinde işler.
Uyarı
İdeal olarak, CategoryName
ve Description
BoundField'ler TemplateFields'e dönüştürülür ve ekleme arabirimleri özelleştirilir.
Description
Örneğin ekleme arabirimi, çok satırlı bir metin kutusu aracılığıyla daha uygun olabilir.
CategoryName
Sütunu NULL
değerlerini kabul etmediğinden, kullanıcının yeni kategori adı için bir değer sağlamasını sağlamak üzere bir RequiredFieldValidator eklenmelidir. Bu adımlar okuyucuya alıştırma olarak bırakılır.
Veri değişikliği arabirimlerini artırmaya ayrıntılı bir bakış için Veri Değiştirme Arabirimini Özelleştirme bölümüne geri bakın.
6. Adım: Karşıya Yüklenen Broşürü Web Sunucusu Dosya Sistemine Kaydetme
Kullanıcı yeni bir kategorinin değerlerini girip Ekle düğmesine tıkladığında bir geri gönderme gerçekleşir ve ekleme iş akışı açılır. İlk olarak, DetailsView'in olayı ItemInserting
tetiklenir. Ardından ObjectDataSource Insert()
yöntemi çağrılır ve tabloya Categories
yeni bir kayıt eklenir. Bundan sonra, DetailsView'in ItemInserted
olayı tetiklenir.
ObjectDataSource Insert()
yöntemi çağrılmadan önce uygun dosya türlerinin kullanıcı tarafından karşıya yüklendiğinden emin olmamız ve ardından broşür PDF dosyasını web sunucusunun dosya sistemine kaydetmemiz gerekir. DetailsView ItemInserting
olayı için bir olay işleyicisi oluşturun ve aşağıdaki kodu ekleyin:
' 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
Olay işleyicisi, DetailsView'in şablonlarından BrochureUpload
FileUpload denetimine başvurarak başlar. Ardından, bir broşür yüklendiyse, yüklenen dosyanın uzantısı incelenir. Uzantı .PDF değilse bir uyarı görüntülenir, ekleme iptal edilir ve olay işleyicisinin yürütülmesi sona erer.
Uyarı
Karşıya yüklenen dosyanın uzantısına güvenmek, dosyanın bir PDF belgesi olduğunu garanti etmek için kesin bir yöntem değildir. Kullanıcının .Brochure
uzantılı geçerli bir PDF belgesi olabilir veya PDF olmayan bir belgeyi alıp ona .pdf
uzantısı vermiş olabilir. Dosya türünün daha kesin bir şekilde doğrulanması için dosyanın ikili içeriğinin program aracılığıyla incelenmesi gerekir. Ancak bu tür kapsamlı yaklaşımlar genellikle fazladır; uzantıyı denetlemek çoğu senaryo için yeterlidir.
Dosyaları Karşıya Yükleme öğreticisinde açıklandığı gibi, bir kullanıcının karşıya yüklemesinin başka bir kullanıcının üzerine yazmaması için dosya sistemine dosya kaydedilirken dikkatli olunması gerekir. Bu eğitimi için karşıya yüklenen dosyayla aynı adı kullanmayı deneyeceğiz. Ancak dizinde ~/Brochures
aynı dosya adına sahip bir dosya zaten varsa, benzersiz bir ad bulunana kadar sonuna bir sayı ekleriz. Örneğin, kullanıcı Meats.pdf
adlı bir broşür dosyasını yüklerse, ancak Meats.pdf
klasöründe ~/Brochures
adlı bir dosya zaten varsa, kaydedilen dosya adını Meats-1.pdf
olarak değiştiririz. Eğer bu varsa, benzersiz bir dosya adı bulunana kadar Meats-2.pdf
denemeye devam edeceğiz.
Aşağıdaki kod, File.Exists(path)
belirtilen dosya adına sahip bir dosyanın zaten var olup olmadığını belirlemek için yöntemini kullanır. Bu durumda, çakışma bulunmadıkça broşür için yeni dosya adları denemeye devam eder.
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
Geçerli bir dosya adı bulunduktan sonra dosyanın dosya sistemine kaydedilmesi ve bu dosya adının veritabanına yazılması için ObjectDataSource brochurePath``InsertParameter
değerinin güncelleştirilmesi gerekir.
Dosya Yükleme öğreticisinde gördüğümüz gibi dosyalar, dosya yükleme kontrolünün SaveAs(path)
yöntemi kullanılarak kaydedilebilir. ObjectDataSource brochurePath
parametresini güncellemek için e.Values
koleksiyonunu kullanın.
' Save the file to disk and set the value of the brochurePath parameter
BrochureUpload.SaveAs(Server.MapPath(brochurePath))
e.Values("brochurePath") = brochurePath
7. Adım: Karşıya Yüklenen Resmi Veritabanına Kaydetme
Karşıya yüklenen resmi yeni Categories
kayıtta depolamak için, karşıya yüklenen ikili içeriği, DetailsView picture
olayında ObjectDataSource'ın ItemInserting
parametresine atamamız gerekir. Ancak bu ödevi vermeden önce karşıya yüklenen resmin başka bir görüntü türü değil JPG olduğundan emin olmamız gerekir. 6. Adım'da olduğu gibi, türünü belirlemek için karşıya yüklenen resmin dosya uzantısını kullanalım.
Categories
tablo NULL
sütun için Picture
değerlerine izin verirken, şu anda tüm kategorilerde bir resim bulunmaktadır. Bu sayfa aracılığıyla yeni bir kategori eklerken kullanıcıyı resim sağlamaya zorlayalım. Aşağıdaki kod, bir resmin karşıya yüklendiğinden ve uygun bir uzantıya sahip olduğundan emin olmak için denetler.
' 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
Bu kod 6. Adımdaki koddan önce yerleştirilmelidir, böylece resim karşıya yüklemeyle ilgili bir sorun varsa, broşür dosyası dosya sistemine kaydedilmeden önce olay işleyicisi sonlandırılır.
Uygun bir dosya yüklendiyse, yüklenen ikili içeriği resim parametresinin değerine aşağıdaki kod satırıyla atayın:
' Set the value of the picture parameter
e.Values("picture") = PictureUpload.FileBytes
TamItemInserting
Olay İşleyicisi
Tamlık için olay işleyicisi ItemInserting
tam olarak aşağıdadır:
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. Adım: SayfayıDisplayCategoryPicture.aspx
Düzeltme
Son birkaç adımda oluşturulan ekleme arabirimini ve ItemInserting
olay işleyicisini test etmek için biraz zaman ayıralım. Sayfayı UploadInDetailsView.aspx
bir tarayıcı üzerinden ziyaret edin ve kategori ekleyin, ancak resmi eklemeden geçin veya JPG formatında olmayan bir resim ya da PDF formatında olmayan bir broşür belirtin. Bu durumların herhangi birinde bir hata iletisi görüntülenir ve ekleme iş akışı iptal edilir.
Şekil 9: Geçersiz Bir Dosya Türü Karşıya Yüklendiyse Bir Uyarı İletisi Görüntüleniyor (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Sayfanın karşıya bir resim yüklenmesini gerektirdiğini ve PDF olmayan veya JPG olmayan dosyaları kabul etmeyeceğini doğruladıktan sonra geçerli bir JPG resmi içeren yeni bir kategori ekleyin ve Broşür alanını boş bırakın. Ekle düğmesine tıkladıktan sonra sayfa tekrar yüklenecek ve karşıya yüklenen görüntünün ikili içeriği doğrudan veritabanında depolanarak Categories
tablosuna yeni bir kayıt eklenecek. GridView güncelleştirilir ve yeni eklenen kategori için bir satır gösterir, ancak Şekil 10'da gösterildiği gibi yeni kategori resmi doğru işlenmez.
Şekil 10: Yeni Kategori resmi görüntülenmiyor (Tam boyutlu görüntüyü görüntülemek için tıklayın)
Yeni resmin görüntülenmeme nedeni, belirtilen kategori resmini DisplayCategoryPicture.aspx
döndüren sayfanın OLE üst bilgisine sahip bit eşlemleri işleyecek şekilde yapılandırılmasıdır. Bu 78 baytlık üst bilgi, istemciye geri gönderilmeden önce Picture
sütununun ikili içeriğinden çıkarılır. Ancak yeni kategori için yüklediğimiz JPG dosyasında bu OLE üst bilgisi bulunmadığından, görüntünün ikili verilerinden gerekli ve geçerli baytlar kaldırılıyor.
Artık tabloda Categories
OLE üst bilgilerine sahip bit eşlemler ve JPG'ler bulunduğundan, özgün sekiz kategori için OLE üst bilgisi çıkarma işlemini yapacak, daha yeni kategori kayıtları için ise bu çıkarma işlemini atlayacak şekilde DisplayCategoryPicture.aspx
'i güncelleştirmemiz gerekir. Sonraki öğreticimizde var olan bir kaydın görüntüsünün nasıl güncelleştirildiğini inceleyeceğiz ve tüm eski kategori resimlerini JPG olacak şekilde güncelleştireceğiz. Şimdilik, yalnızca bu özgün sekiz kategori için OLE üst bilgilerini silmek amacıyla aşağıdaki kodu DisplayCategoryPicture.aspx
kullanın.
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
Bu değişiklikle JPG görüntüsü artık GridView'da doğru şekilde işlenir.
Şekil 11: Yeni Kategoriler için JPG Görüntüleri Doğru İşlendi (Tam boyutlu görüntüyü görüntülemek için tıklayın)
9. Adım: İstisna Durumunda Broşürü Silme
İkili verileri web sunucusunun dosya sisteminde depolamanın zorluklarından biri, veri modeli ile ikili verileri arasında bir bağlantı kesilmesine neden olmasıdır. Bu nedenle, bir kayıt her silindiğinde, dosya sistemindeki ilgili ikili veriler de kaldırılmalıdır. Bu, ekleme sırasında da devreye girilebilir. Aşağıdaki senaryoyu göz önünde bulundurun: Kullanıcı geçerli bir resim ve broşür belirterek yeni bir kategori ekler. Ekle düğmesine tıkladığınızda, bir geri yükleme işlemi gerçekleşir ve DetailsView'ın ItemInserting
olayı tetiklenerek broşürü web sunucusunun dosya sistemine kaydeder. Daha sonra, Insert()
yöntemi çağrılır, bu da CategoriesBLL
sınıfının InsertWithPicture
yöntemini çağırır, bu da CategoriesTableAdapter
sınıfının InsertWithPicture
yöntemini çağırır.
Şimdi veritabanı çevrimdışıysa veya SQL deyiminde INSERT
bir hata varsa ne olur? INSERT başarısız olacağı açıktır, bu nedenle veritabanına yeni kategori satırı eklenmez. Ancak web sunucusunun dosya sisteminde yüklü broşür dosyası hala var! Ekleme iş akışı sırasında bir özel durum karşısında bu dosyanın silinmesi gerekir.
Daha önce, bir ASP.NET Sayfasında BLL ve DAL-Level Özel Durumlarını İşleme öğreticisinde açıklandığı gibi, mimarinin derinliklerinden bir özel durum oluştuğunda, çeşitli katmanlarda yukarı doğru iletilir. Sunu Katmanı'nda DetailsView s ItemInserted
olayından bir özel durum oluşup oluşmadığını belirleyebiliriz. Bu olay işleyicisi, ObjectDataSource'un InsertParameters
değerlerini sağlar. Bu nedenle, bir özel durum olup olmadığını denetleyerek ve varsa ObjectDataSource ItemInserted
parametresi tarafından belirtilen dosyayı silerek olay için brochurePath
bir olay işleyicisi oluşturabiliriz:
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
Özet
İkili veri içeren kayıtlar eklemek için web tabanlı bir arabirim sağlamak için gerçekleştirilmesi gereken birkaç adım vardır. İkili veriler doğrudan veritabanına depolanıyorsa, ikili verilerin eklendiği durumu işlemek için belirli yöntemler ekleyerek mimariyi güncelleştirmeniz gerekebilir. Mimari güncelleştirildikten sonra, sonraki adım ekleme arabirimini oluşturmaktır. Bu arabirim, her ikili veri alanı için FileUpload denetimi içerecek şekilde özelleştirilmiş bir DetailsView kullanılarak gerçekleştirilebilir. Karşıya yüklenen veriler daha sonra web sunucusunun dosya sistemine kaydedilebilir veya DetailsView ItemInserting
olay işleyicisindeki bir veri kaynağı parametresine atanabilir.
İkili verileri dosya sistemine kaydetmek, verileri doğrudan veritabanına kaydetmekten daha fazla planlama gerektirir. Bir kullanıcının karşıya yükleme işleminin başka bir kullanıcının üzerine yazılmasını önlemek için bir adlandırma düzeni seçilmelidir. Ayrıca, veritabanı ekleme işlemi başarısız olursa karşıya yüklenen dosyayı silmek için ek adımlar atılmalıdır.
Artık sisteme broşür ve resimle yeni kategoriler ekleme olanağımız var, ancak mevcut bir kategorinin ikili verilerinin nasıl güncelleştirildiğini veya silinen bir kategori için ikili verilerin doğru şekilde nasıl kaldırılacağını henüz incelemedik. Sonraki öğreticide bu iki konuyu inceleyeceğiz.
Mutlu Programlama!
Yazar Hakkında
Yedi ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışır. Son kitabı Sams Teach Yourself ASP.NET 24 Hours 2.0'dır. Ona adresinden mitchell@4GuysFromRolla.comulaşabilirsiniz.
Özel Teşekkürler
Bu eğitim serisi, birçok yararlı kişi tarafından incelendi. Bu öğreticinin baş gözden geçirenleri Dave Gardner, Teresa Murphy ve Bernadette Leigh oldu. Yaklaşan MSDN makalelerimi gözden geçirmek istiyor musunuz? Öyleyse, mitchell@4GuysFromRolla.com'a bir mesaj bırakın.