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

tarafından Scott Mitchell

PDF’yi İndir

Bu öğreticide, kullanıcının hem metin verileri 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 nasıl ilişkilendirebileceğimiz 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 kategorinin resmi, diğeri broşür için olmak üzere iki FileUpload denetimi bulunacaktır. Karşıya yüklenen resim doğrudan yeni kaydın sütununda depolanırken, broşür yeni kaydın Picture~/BrochuresBrochurePath sütununa kaydedilen dosyanın yolunu içeren klasöre kaydedilir.

Bu yeni web sayfasını oluşturmadan önce mimariyi güncelleştirmemiz gerekir. Ana CategoriesTableAdapter sorgu sütunu almaz Picture . Sonuç olarak, otomatik oluşturulan Insert yöntemin yalnızca , Descriptionve BrochurePath alanları için CategoryNamegirişleri vardır. 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: yöntemine yöntemInsertWithPictureeklemeCategoriesTableAdapter

Veri Erişim Katmanı Oluşturma öğreticisinde gerisini oluşturduğunuzdaCategoriesTableAdapter, bunu ana sorguyu temel alan , UPDATEve DELETE deyimlerini otomatik olarak oluşturacak INSERTşekilde yapılandırdık. Ayrıca TableAdapter'a, , ve yöntemlerini Insertoluşturan DB Doğrudan yaklaşımını kullanma talimatı verdikDelete. Update 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, sütunu kullanmak için ana sorguyu BrochurePath genişlettikCategoriesTableAdapter.

Ana sorgu sütuna CategoriesTableAdapterPicture başvurmadığından, yeni kayıt ekleyemiyoruz veya mevcut bir kaydı sütun için Picture bir değerle güncelleştiremiyoruz. 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 olarak oluşturulan INSERT deyimi özelleştirmeyle ilgili sorun, özelleştirmelerimizin sihirbaz tarafından üzerine yazılmasını riske atmamızdır. Örneğin, deyimini sütunun INSERT kullanımını içerecek şekilde özelleştirdiğimizi Picture düşünün. Bu, TableAdapter Insert yöntemini, kategori resminin ikili verileri için ek bir giriş parametresi içerecek şekilde güncelleştirir. Daha sonra bu DAL yöntemini kullanmak ve Bu BLL yöntemini Sunu Katmanı aracılığıyla çağırmak için İş Mantığı Katmanı'nda bir yöntem oluşturabiliriz ve her şey harika çalışır. Yani, TableAdapter Yapılandırma sihirbazı aracılığıyla TableAdapter'ı bir sonraki yapılandırışımıza kadar. Sihirbaz tamamlanır tamamlanmaz deyimindeki INSERT özelleştirmelerimizin üzerine yazılır, Insert yöntem eski biçimine döner ve kodumuz artık derlenmez!

Not

Geçici SQL deyimleri yerine saklı yordamlar kullanılırken bu rahatsızlık sorun oluşturmaz. Gelecekteki bir öğreticide, Veri Erişim Katmanı'ndaki geçici SQL deyimleri dışında saklı yordamları kullanmayı keşfedeceğ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. adlı InsertWithPicturebu yöntem, , , DescriptionBrochurePathve sütunları için CategoryNamedeğerleri kabul eder ve Picture dört değerin tümünü yeni bir kayıtta depolayan bir deyimi yürütürINSERT.

Yazılan Veri Kümesi'ni açın ve Tasarım Aracı s üst bilgisine CategoriesTableAdapter sağ tıklayın ve bağlam menüsünden 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ımda oluşturulacak sorgu türü istenir. Tabloya yeni 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 resmi 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, , Descriptionve BrochurePath değerlerini ekleyen CategoryNamebir INSERT deyimdir. Sütunun bir @Picture parametreyle birlikte eklenmesi için deyimini Picture güncelleştirin, ö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 sınıfında giriş üç string s ve dizi olarak kabul eden adlı InsertWithPicture bir byte yöntem CategoriesBLL oluşturun. Giriş string parametreleri kategorinin adı, açıklaması ve broşür dosyası yolu için, byte dizi ise 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 void InsertWithPicture(string categoryName, string description, 
    string brochurePath, byte[] picture)
{
    Adapter.InsertWithPicture(categoryName, description, brochurePath, picture);
}

Not

Yöntemini BLL'ye eklemeden önce Typed DataSet'i InsertWithPicture kaydettiğinizden emin olun. CategoriesTableAdapter Sınıf kodu Türü Yazılan DataSet'i temel alarak otomatik olarak oluşturulduğundan, değişikliklerinizi önce Türü Yazılan Veri Kümesi'ne 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ü indirme bağlantısını görüntülemek için TemplateField ve ImageField içeren bir GridView kullandık. Şimdi bu öğreticinin işlevselliğini çoğaltarak hem tüm mevcut kategorileri listeleyen hem de yeni kategorilerin oluşturulmasına izin veren bir sayfa oluşturalım.

Başlangıç olarak klasörden DisplayOrDownload.aspx sayfayı BinaryData açın. Kaynak görünümüne gidin ve GridView ve ObjectDataSource bildirim temelli söz dizimini kopyalayıp içindeki UploadInDetailsView.aspxöğesinin <asp:Content> içine yapıştırın. Ayrıca, yönteminin arka kod GenerateBrochureLink arkası sınıfından DisplayOrDownload.aspx öğesine kopyalamayı UploadInDetailsView.aspxunutmayın.

bildirim temelli söz dizimini DisplayOrDownload.aspx UploadInDetailsView.aspx kopyalayıp yapıştırın

Şekil 3: Bildirim Temelli Söz Dizimini kopyalayıp DisplayOrDownload.aspx yapıştırın UploadInDetailsView.aspx (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: 'yiCategoriesDataSourceEkleme Desteğine Göre Yapılandırma

CategoriesDataSource GridView tarafından Categories kullanılan ObjectDataSource şu anda veri ekleme olanağı sağlamamaktadır. Bu veri kaynağı denetimi aracılığıyla eklemeyi desteklemek için yöntemini temel alınan nesnesindeki CategoriesBLLbir yöntemle eşlememiz Insert gerekir. Özellikle, 2InsertWithPicture. Adımda yeniden eklediğimiz yöntemle eşlemek CategoriesBLL 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 ile CategoriesBLLçalışmak üzere yapılandırıldığı nesne gösterilir. Bu ayarı olduğu gibi 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)

Not

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çtiğinizde yapmış olabileceğiniz tüm alan özelleştirmelerinin üzerine yazılır.

Sihirbazı tamamladıktan sonra, ObjectDataSource artık özelliği InsertParameters ve dört kategori sütunu için InsertMethod aşağıdaki bildirim temelli işaretlemenin gösterildiği gibi bir değer içerecektir:

<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 açıklandığı gibi DetailsView denetimi, ekleme desteği olan bir veri kaynağı denetimiyle çalışırken kullanılabilecek yerleşik bir ekleme arabirimi sağlar. Kullanıcının hızla yeni bir kategori eklemesine olanak tanıyarak ekleme arabirimini kalıcı olarak işleyen GridView'un üzerine bu sayfaya bir DetailsView denetimi ekleyelim. DetailsView'a yeni bir kategori eklendikten sonra, altındaki GridView otomatik olarak yenilenir ve yeni kategoriyi görüntüler.

Başlangıç olarak, Toolbox'tan GridView'un üzerindeki Tasarım Aracı bir DetailsView sürükleyin, özelliğini IDNewCategory olarak ayarlayın ve ve Width özellik değerlerini temizleyinHeight. DetailsView'un akıllı etiketinden var olan CategoriesDataSource etikete bağlayın ve Eklemeyi Etkinleştir onay kutusunu işaretleyin.

CategoryID özelliğinin NewCategory, boş Height ve Width özellik değerleri ve Eklemeyi Etkinleştir onay kutusunun seçili olduğu DetailsView'un açık olduğunu gösteren 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)

Ekleme arabiriminde DetailsView'ı kalıcı olarak işlemek için özelliğini olarak InsertayarlayınDefaultMode.

Özelliği olarak ayarlandığındanfalse, Ekleme arabiriminde InsertVisible BoundField işlenmese de CategoryID DetailsView'da beş BoundField DescriptionCategoryNameCategoryID, ve NumberOfProductsBrochurePath olduğunu unutmayın. 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 resim yüklemelerine ve broşür için PDF yüklemelerine izin vermemiz gerekir.

NumberOfProducts DetailsView'dan BoundField öğesini tamamen kaldırın ve ardından ve BrochurePath BoundFields özelliklerini CategoryName sırasıyla Category ve Broşür olarak güncelleştirinHeaderText. 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 penceresinin ekran görüntüsü.

Şekil 7: DetailsView'ı ve Eklemeyi Etkinleştir'e CategoriesDataSource bağlama

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. Ancak yalnızca gerekli InsertItemTemplate olduğu için diğer iki şablonu kaldırmaktan çekinmeyin. 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 akıllı etiketinden Şablonları Düzenle seçeneğini belirleyin ve ardından açılan listeden TemplateField'leri InsertItemTemplate seçinBrochurePath. TextBox'ı kaldırın ve araç kutusundan fileupload denetimini şablona sürükleyin. FileUpload denetimini olarak IDBrochureUploadayarlayın. Benzer şekilde, TemplateField's InsertItemTemplateöğesine Picture bir FileUpload denetimi ekleyin. Bu FileUpload denetimini olarak IDPictureUploadayarlayın.

InsertItemTemplate'a FileUpload Denetimi Ekleme

Şekil 8: Dosyasına FileUpload Denetimi InsertItemTemplate Ekleme (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Bu eklemeleri yaptıktan sonra, iki TemplateField bildirim temelli söz dizimi 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 mı yoksa yalnızca GIF veya JPG gibi belirli bir türdeki görüntü dosyalarına mı izin veririz? Farklı dosya türlerine izin vermek için, şemayı Categories dosya türünü yakalayan bir sütun içerecek şekilde genişletmemiz gerekir; böylece bu tür istemciye içinde DisplayCategoryPicture.aspxaracılığıyla Response.ContentType gönderilebilir. Böyle bir sütuna sahip olmadığımıza göre, kullanıcıların yalnızca belirli bir görüntü dosyası türünü 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.

Bir 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 altına bir Label Web denetimi ekleyin. ID özelliğini olarak UploadWarningayarlayın, özelliğini temizleyinText, özelliğini Uyarı olarak, Visible ve EnableViewState özelliklerini olarak falseayarlayınCssClass. 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.

Not

İdeal olarak, CategoryName ve Description BoundField'ler TemplateFields'e dönüştürülür ve arabirimleri özelleştirilir. Description Örneğin ekleme arabirimi, çok satırlı bir metin kutusu aracılığıyla daha uygun olabilir. CategoryName Sütun değerleri kabul NULL etmediğinden, kullanıcının yeni kategori adı için bir değer sağladığından emin olmak için 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 dönü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 olayıItemInserting tetikler. Ardından ObjectDataSource Insert() yöntemi çağrılır ve bu da tabloya yeni bir kayıt eklenmesine Categories neden olur. Bundan sonra DetailsView olayıItemInserted tetikler.

ObjectDataSource Insert() yöntemi çağrılmadan önce kullanıcı tarafından uygun dosya türlerinin yüklendiğinden emin olmalı ve sonra broşür PDF dosyasını web sunucusunun dosya sistemine kaydetmeliyiz. DetailsView ItemInserting olayı için bir olay işleyicisi oluşturun ve aşağıdaki kodu ekleyin:

// Reference the FileUpload control
FileUpload BrochureUpload = 
    (FileUpload)NewCategory.FindControl("BrochureUpload");
if (BrochureUpload.HasFile)
{
    // Make sure that a PDF has been uploaded
    if (string.Compare(System.IO.Path.GetExtension
        (BrochureUpload.FileName), ".pdf", true) != 0)
    {
        UploadWarning.Text = 
            "Only PDF documents may be used for a category's brochure.";
        UploadWarning.Visible = true;
        e.Cancel = true;
        return;
    }
}

Olay işleyicisi, DetailsView şablonlarından BrochureUpload FileUpload denetimine başvurarak başlar. Ardından, bir broşür karşıya yüklendiyse, karşıya yüklenen dosyanın uzantısı incelenmiştir. Uzantı .PDF değilse bir uyarı görüntülenir, ekleme iptal edilir ve olay işleyicisinin yürütülmesi sona erer.

Not

Karşıya yüklenen dosyanın uzantısına güvenmek, karşıya yüklenen dosyanın bir PDF belgesi olduğundan emin olmak için kesin bir yöntem değildir. Kullanıcının uzantısına .Brochuresahip geçerli bir PDF belgesi olabilir veya PDF olmayan bir belge alıp uzantı vermiş .pdf olabilir. Dosya türünü daha kesin bir şekilde doğrulamak için dosyanın ikili içeriğinin program aracılığıyla incelenmesi gerekir. Ancak bu tür kapsamlı yaklaşımlar genellikle aşırıya kaçmaktadı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 dosyaları dosya sistemine kaydederken dikkatli olunması gerekir. Bu öğretici 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ı adlı Meats.pdfbir broşür dosyasını karşıya yüklerse ancak klasörde adlı Meats.pdf~/Brochures bir dosya zaten varsa, kaydedilen dosya adını Meats-1.pdfolarak değiştiririz. Bu varsa, benzersiz bir dosya adı bulunana kadar , vb. deneyeceğiz Meats-2.pdf.

Aşağıdaki kod, File.Exists(path) belirtilen dosya adına sahip bir dosyanın zaten mevcut olup olmadığını belirlemek için yöntemini kullanır. Bu durumda, çakışma bulunıncaya kadar broşür için yeni dosya adlarını denemeye devam eder.

const string BrochureDirectory = "~/Brochures/";
string brochurePath = BrochureDirectory + BrochureUpload.FileName;
string fileNameWithoutExtension = 
    System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName);
int iteration = 1;
while (System.IO.File.Exists(Server.MapPath(brochurePath)))
{
    brochurePath = string.Concat(BrochureDirectory, 
        fileNameWithoutExtension, "-", iteration, ".pdf");
    iteration++;
}

Geçerli bir dosya adı bulunduktan sonra dosyanın dosya sistemine kaydedilmesi ve ObjectDataSource brochurePath``InsertParameter değerinin bu dosya adının veritabanına yazılması için güncelleştirilmesi gerekir. Dosyaları Karşıya Yükleme öğreticisinde gördüğümüz gibi, dosya FileUpload denetimi s SaveAs(path) yöntemi kullanılarak kaydedilebilir. ObjectDataSource brochurePath parametresini güncelleştirmek için koleksiyonunu kullanın e.Values .

// 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 s ItemInserting olayında ObjectDataSource picture parametresine atamamız gerekir. Ancak bu ödevi yapmadan ö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 sütun için değerlere Picture izin verirkenNULL, tüm kategorilerde şu anda bir resim vardı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
FileUpload PictureUpload = (FileUpload)NewCategory.FindControl("PictureUpload");
if (PictureUpload.HasFile)
{
    // Make sure that a JPG has been uploaded
    if (string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), 
            ".jpg", true) != 0 &&
        string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), 
            ".jpeg", true) != 0)
    {
        UploadWarning.Text = 
            "Only JPG documents may be used for a category's picture.";
        UploadWarning.Visible = true;
        e.Cancel = true;
        return;
    }
}
else
{
    // No picture uploaded!
    UploadWarning.Text = 
        "You must provide a picture for the new category.";
    UploadWarning.Visible = true;
    e.Cancel = true;
    return;
}

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 dosyanın karşıya yüklendiğini varsayarsak, karşıya yüklenen ikili içeriği aşağıdaki kod satırıyla picture parametresinin değerine atayın:

// Set the value of the picture parameter
e.Values["picture"] = PictureUpload.FileBytes;

TamItemInsertingOlay İşleyicisi

Tamlık için olay işleyicisi tam olarak aşağıdadır ItemInserting :

protected void NewCategory_ItemInserting(object sender, DetailsViewInsertEventArgs e)
{
    // Reference the FileUpload controls
    FileUpload PictureUpload = (FileUpload)NewCategory.FindControl("PictureUpload");
    if (PictureUpload.HasFile)
    {
        // Make sure that a JPG has been uploaded
        if (string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), 
                ".jpg", true) != 0 &&
            string.Compare(System.IO.Path.GetExtension(PictureUpload.FileName), 
                ".jpeg", true) != 0)
        {
            UploadWarning.Text = 
                "Only JPG documents may be used for a category's picture.";
            UploadWarning.Visible = true;
            e.Cancel = true;
            return;
        }
    }
    else
    {
        // No picture uploaded!
        UploadWarning.Text = 
            "You must provide a picture for the new category.";
        UploadWarning.Visible = true;
        e.Cancel = true;
        return;
    }
    // Set the value of the picture parameter
    e.Values["picture"] = PictureUpload.FileBytes;
    
    
    // Reference the FileUpload controls
    FileUpload BrochureUpload = 
        (FileUpload)NewCategory.FindControl("BrochureUpload");
    if (BrochureUpload.HasFile)
    {
        // Make sure that a PDF has been uploaded
        if (string.Compare(System.IO.Path.GetExtension(BrochureUpload.FileName), 
            ".pdf", true) != 0)
        {
            UploadWarning.Text = 
                "Only PDF documents may be used for a category's brochure.";
            UploadWarning.Visible = true;
            e.Cancel = true;
            return;
        }
        const string BrochureDirectory = "~/Brochures/";
        string brochurePath = BrochureDirectory + BrochureUpload.FileName;
        string fileNameWithoutExtension = 
            System.IO.Path.GetFileNameWithoutExtension(BrochureUpload.FileName);
        int iteration = 1;
        while (System.IO.File.Exists(Server.MapPath(brochurePath)))
        {
            brochurePath = string.Concat(BrochureDirectory, fileNameWithoutExtension, 
                "-", iteration, ".pdf");
            iteration++;
        }
        // Save the file to disk and set the value of the brochurePath parameter
        BrochureUpload.SaveAs(Server.MapPath(brochurePath));
        e.Values["brochurePath"] = brochurePath;
    }
}

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. Tarayıcı üzerinden sayfayı UploadInDetailsView.aspx ziyaret edin ve kategori eklemeyi deneyip resmi atlayarak JPG olmayan bir resim veya PDF olmayan bir broşür belirtin. Bu durumlarda bir hata iletisi görüntülenir ve ekleme iş akışı iptal edilir.

Geçersiz Bir Dosya Türü Karşıya Yüklenirse 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üklenmesi gerektiğ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 geri yüklenir ve karşıya yüklenen görüntünün ikili içeriği doğrudan veritabanında depolanmış şekilde tabloya yeni bir kayıt eklenir Categories . 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 resmi görüntülemek için tıklayın)

Yeni resmin görüntülenmeme nedeni, belirtilen kategorinin DisplayCategoryPicture.aspx resmini 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 sütunun Picture ikili içeriğinden çıkarılır. Ancak yeni kategori için karşıya yüklediğimiz JPG dosyasında bu OLE üst bilgisi yok; bu nedenle, görüntünün ikili verilerinden geçerli, gerekli baytlar kaldırılıyor.

Artık tabloda HEM OLE üst bilgileri hem de JPG'ler Categories içeren bit eşlemler bulunduğundan, özgün sekiz kategori için OLE üst bilgisinin çıkarılıp yeni kategori kayıtları için bu striptiz işlemini atlayacak şekilde güncelleştirmemiz DisplayCategoryPicture.aspx gerekir. Sonraki öğreticimizde mevcut bir kaydın görüntüsünün nasıl güncelleştirildiğini inceleyecek ve tüm eski kategori resimlerini JPG olacak şekilde güncelleştireceğiz. Şimdilik, ole üst bilgilerini yalnızca özgün sekiz kategori için şerit için aşağıdaki kodu DisplayCategoryPicture.aspx kullanın:

protected void Page_Load(object sender, EventArgs e)
{
    int categoryID = Convert.ToInt32(Request.QueryString["CategoryID"]);
    // Get information about the specified category
    CategoriesBLL categoryAPI = new CategoriesBLL();
    Northwind.CategoriesDataTable categories = 
        categoryAPI.GetCategoryWithBinaryDataByCategoryID(categoryID);
    Northwind.CategoriesRow category = categories[0];
    if (categoryID <= 8)
    {
        // For older categories, we must strip the OLE header... images are bitmaps
        // 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 int OleHeaderLength = 78;
        int strippedImageLength = category.Picture.Length - OleHeaderLength;
        byte[] strippedImageData = new byte[strippedImageLength];
        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);
    }
}

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 Doğru İşleniyor

Şekil 11: Yeni Kategoriler için JPG Görüntüleri Doğru İşleniyor (Tam boyutlu görüntüyü görüntülemek için tıklayın)

9. Adım: Özel Durumun Karşısında Broşürü Silme

İkili verileri web sunucusunun dosya sisteminde depolamanın zorluklarından biri, veri modeliyle ikili verileri arasında bir bağlantı kesilmesine neden olmasıdır. Bu nedenle, bir kayıt her silindiğinde, dosya sistemindeki ilgili ikili verilerin de kaldırılması gerekir. Bu, ekleme sırasında da devreye girer. 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ıktan sonra bir geri gönderme gerçekleşir ve DetailsView ItemInserting olayı tetiklenip broşürü web sunucusunun dosya sistemine kaydeder. Daha sonra, s yöntemini çağıran sınıfın CategoriesBLLInsertWithPicture yöntemini çağıran CategoriesTableAdapterInsertWithPicture ObjectDataSource Insert() yöntemi çağrılır.

Şimdi veritabanı çevrimdışıysa veya SQL deyiminde INSERT bir hata varsa ne olur? INSERT başarısız olur, bu nedenle veritabanına yeni kategori satırı eklenmez. Ancak karşıya yüklenen broşür dosyası hala web sunucusunun dosya sisteminde duruyor! Bu dosyanın, ekleme iş akışı sırasında bir özel durum karşısında 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 katmanlar arasında kabarır. Sunu Katmanı'nda DetailsView ItemInserted olayından bir özel durum oluşup oluşmadığını belirleyebiliriz. Bu olay işleyicisi, ObjectDataSource'un InsertParametersdeğerlerini de sağlar. Bu nedenle, bir özel durum olup olmadığını denetleyerek ve varsa ObjectDataSource brochurePath parametresi tarafından belirtilen dosyayı silerek olay için ItemInserted bir olay işleyicisi oluşturabiliriz:

protected void NewCategory_ItemInserted
    (object sender, DetailsViewInsertedEventArgs e)
{
    if (e.Exception != null)
    {
        // Need to delete brochure file, if it exists
        if (e.Values["brochurePath"] != null)
            System.IO.File.Delete(Server.MapPath(
                e.Values["brochurePath"].ToString()));
    }
}

Ö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ğına sahibiz, ancak henüz mevcut bir kategorinin ikili verilerini güncelleştirme veya silinen bir kategori için ikili verileri doğru şekilde kaldırma konularına bakmadık. 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ışmaktadır. Son kitabı Sams Teach Yourself ASP.NET 24 Saat içinde 2.0. Adresine adresinden veya adresinden ulaşabileceğiniz http://ScottOnWriting.NETblogu aracılığıyla ulaşabilirsinizmitchell@4GuysFromRolla.com.

Özel Teşekkürler

Bu öğretici serisi birçok yararlı gözden geçiren tarafından gözden geçirildi. 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, bana bir satır mitchell@4GuysFromRolla.combırakın.