Yeni Kayıt Eklerken Karşıya Dosya Yükleme Seçeneği Ekleme (C#)
tarafından Scott Mitchell
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
~/Brochures
BrochurePath
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 , Description
ve BrochurePath
alanları için CategoryName
giriş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öntemInsertWithPicture
eklemeCategoriesTableAdapter
Veri Erişim Katmanı Oluşturma öğreticisinde gerisini oluşturduğunuzdaCategoriesTableAdapter
, bunu ana sorguyu temel alan , UPDATE
ve DELETE
deyimlerini otomatik olarak oluşturacak INSERT
şekilde yapılandırdık. Ayrıca TableAdapter'a, , ve yöntemlerini Insert
oluşturan DB Doğrudan yaklaşımını kullanma talimatı verdikDelete
. Update
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, sütunu kullanmak için ana sorguyu BrochurePath
genişlettikCategoriesTableAdapter
.
Ana sorgu sütuna CategoriesTableAdapter
Picture
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ı InsertWithPicture
bu yöntem, , , Description
BrochurePath
ve sütunları için CategoryName
değ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.
Ş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, , Description
ve BrochurePath
değerlerini ekleyen CategoryName
bir 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.
Ş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.aspx
unutmayı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.
Ş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: 'yiCategoriesDataSource
Ekleme 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 CategoriesBLL
bir 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.
Ş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 ID
NewCategory
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.
Ş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 Insert
ayarlayınDefaultMode
.
Özelliği olarak ayarlandığındanfalse
, Ekleme arabiriminde InsertVisible
BoundField işlenmese de CategoryID
DetailsView'da beş BoundField Description
CategoryName
CategoryID
, ve NumberOfProducts
BrochurePath
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 NumberOfProducts
bir 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.
Ş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
, EditItemTemplate
ve InsertItemTemplate
iç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 ID
BrochureUpload
ayarlayın. Benzer şekilde, TemplateField's InsertItemTemplate
öğesine Picture
bir FileUpload denetimi ekleyin. Bu FileUpload denetimini olarak ID
PictureUpload
ayarlayın.
Ş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.aspx
aracı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 UploadWarning
ayarlayın, özelliğini temizleyinText
, özelliğini Uyarı olarak, Visible
ve EnableViewState
özelliklerini olarak false
ayarlayı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 .Brochure
sahip 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.pdf
bir 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.pdf
olarak 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;
TamItemInserting
Olay İş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.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. 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.
Ş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.
Ş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.
Ş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 CategoriesBLL
InsertWithPicture
yöntemini çağıran CategoriesTableAdapter
InsertWithPicture
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 InsertParameters
değ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.