Aracılığıyla paylaş


Yeni Kayıt Eklerken Karşıya Dosya Yükleme Seçeneği Ekleme (VB)

tarafından Scott Mitchell

PDF'i indirin

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:InsertWithPictureyö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, UPDATEve 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.

INSERT Seçeneğini Belirleyin

Ş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.

Yeni TableAdapter Yöntemini InsertWithPicture olarak adlandırı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.

Bildirim temelli söz dizimini DisplayOrDownload.aspx dosyasından UploadInDetailsView.aspx dosyasına kopyalayıp yapıştırın

Şekil 3: Bildirim Temelli Söz Dizimini 'den DisplayOrDownload.aspxUploadInDetailsView.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.

Şimdi her kategoriyi kendi ikili verileriyle birlikte 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.

ObjectDataSource'ı InsertWithPicture Yöntemini kullanacak şekilde yapılandırma

Ş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.

CategoryID özelliğinin NewCategory olarak ayarlandığı, Height ve Width özellik değerlerinin boş olduğu ve Eklemeyi Etkinleştir onay kutusunun seçili olduğu DetailsView ekran görüntüsü.

Ş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 NumberOfProductsbir 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.

TemplateField, Picture ve HeaderText vurgulanmış alanlar penceresini gösteren ekran görüntüsü.

Ş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, EditItemTemplateve InsertItemTemplateiç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.

InsertItemTemplate'a FileUpload Denetimi Ekleme

Ş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

TamItemInsertingOlay İş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.aspxDü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.

Geçersiz Bir Dosya Türü Karşıya Yüklendiyse Bir Uyarı İletisi Görüntülenir

Ş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.

Yeni Kategori resmi görüntülenmiyor

Ş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.

Yeni Kategoriler için JPG Görüntüleri Başarıyla Oluşturuldu

Ş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.