Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Scott Mitchell
Tutorial ini menunjukkan cara membuat antarmuka Web yang memungkinkan pengguna memasukkan data teks dan mengunggah file biner. Untuk mengilustrasikan opsi yang tersedia untuk menyimpan data biner, satu file akan disimpan dalam database sementara yang lain disimpan dalam sistem file.
Pendahuluan
Dalam dua tutorial sebelumnya kami menjelajahi teknik untuk menyimpan data biner yang terkait dengan model data aplikasi, melihat cara menggunakan kontrol FileUpload untuk mengirim file dari klien ke server web, dan melihat cara menyajikan data biner ini dalam kontrol Web data. Namun, kami belum berbicara tentang cara mengaitkan data yang diunggah dengan model data.
Dalam tutorial ini kita akan membuat halaman web untuk menambahkan kategori baru. Selain TextBoxes untuk nama dan deskripsi kategori, halaman ini harus menyertakan dua kontrol FileUpload satu untuk gambar kategori baru dan satu untuk brosur. Gambar yang diunggah akan disimpan langsung di kolom rekaman baru, Picture
sedangkan brosur akan disimpan ke ~/Brochures
folder dengan jalur ke file yang disimpan di kolom rekaman baru BrochurePath
.
Sebelum membuat halaman web baru ini, kita harus memperbarui arsitektur. Kueri utama CategoriesTableAdapter
tidak mengambil kolom Picture
. Akibatnya, metode Insert
yang dihasilkan secara otomatis hanya memiliki input untuk bidang CategoryName
, Description
, dan BrochurePath
. Oleh karena itu, kita perlu membuat metode tambahan di TableAdapter yang meminta keempat Categories
bidang. Kelas CategoriesBLL
di Lapisan Logika Bisnis juga perlu diperbarui.
Langkah 1: MenambahkanInsertWithPicture
Metode keCategoriesTableAdapter
Ketika kami membuat CategoriesTableAdapter
kembali dalam tutorial Membuat Lapisan Akses Data , kami mengonfigurasinya untuk secara otomatis menghasilkan INSERT
pernyataan , UPDATE
, dan DELETE
berdasarkan kueri utama. Selain itu, kami menginstruksikan TableAdapter untuk menggunakan pendekatan DB Direct, yang membuat metode Insert
, Update
, dan Delete
. Metode ini menjalankan pernyataan INSERT
, UPDATE
, dan DELETE
yang dihasilkan secara otomatis dan, akibatnya, menerima parameter input berdasarkan kolom yang dikembalikan oleh kueri utama. Dalam tutorial Mengunggah File, kami menambah kueri utama CategoriesTableAdapter
agar menggunakan kolom BrochurePath
.
CategoriesTableAdapter
Karena kueri utama tidak mereferensikan kolom Picture
, kita tidak dapat menambahkan rekaman baru atau memperbarui rekaman yang sudah ada dengan nilai untuk kolom Picture
. Untuk mengambil informasi ini, kita dapat membuat metode baru di TableAdapter yang digunakan khusus untuk menyisipkan rekaman dengan data biner atau kita dapat menyesuaikan pernyataan yang dihasilkan INSERT
secara otomatis. Masalah dengan menyesuaikan pernyataan yang dihasilkan INSERT
secara otomatis adalah kami berisiko penyesuaian kami ditimpa oleh wizard. Misalnya, bayangkan bahwa kita menyesuaikan pernyataan INSERT
untuk menyertakan penggunaan kolom Picture
. Ini akan memperbarui metode TableAdapter s Insert
untuk menyertakan parameter input tambahan untuk data biner gambar kategori. Kita kemudian dapat membuat metode di Lapisan Logika Bisnis untuk menggunakan metode DAL ini dan memanggil metode BLL ini melalui Lapisan Presentasi, dan semuanya akan bekerja dengan luar biasa. Artinya, sampai lain kali kami mengonfigurasi TableAdapter melalui wizard Konfigurasi TableAdapter. Begitu wizard selesai, penyesuaian kami ke INSERT
statement akan ditimpa, Insert
metode akan kembali ke bentuk lamanya, dan kode kami tidak dapat lagi dikompilasi!
Nota
Gangguan ini bukan masalah saat menggunakan prosedur tersimpan alih-alih pernyataan SQL ad-hoc. Tutorial di masa mendatang akan menjelajahi menggunakan prosedur tersimpan sebagai pengganti pernyataan SQL ad-hoc di Lapisan Akses Data.
Untuk menghindari potensi sakit kepala ini, daripada menyesuaikan pernyataan SQL yang dihasilkan secara otomatis, mari kita buat metode baru untuk TableAdapter. Metode ini, bernama InsertWithPicture
, akan menerima nilai untuk kolom CategoryName
, Description
, BrochurePath
, dan Picture
dan menjalankan perintah INSERT
yang menyimpan keempat nilai dalam rekaman baru.
Buka DataSet Tertulis dan, dari Desainer, klik kanan pada header CategoriesTableAdapter
dan pilih Tambahkan Kueri dari menu konteks. Ini meluncurkan Panduan Konfigurasi Kueri TableAdapter, yang dimulai dengan menanyakan kepada kami bagaimana kueri TableAdapter harus mengakses database. Pilih Gunakan pernyataan SQL dan klik Berikutnya. Langkah berikutnya meminta jenis kueri yang akan dibuat. Karena kita membuat kueri untuk menambahkan rekaman baru ke Categories
tabel, pilih INSERT dan klik Berikutnya.
Gambar 1: Pilih Opsi INSERT (Klik untuk melihat gambar ukuran penuh)
Kita sekarang perlu menentukan INSERT
pernyataan SQL. Panduan secara otomatis menyarankan pernyataan yang INSERT
sesuai dengan kueri utama TableAdapter. Dalam hal ini, pernyataan ini merupakan sebuah pernyataan yang menyisipkan nilai INSERT
, CategoryName
, dan Description
. Perbarui pernyataan sehingga Picture
kolom disertakan bersama dengan @Picture
parameter, seperti:
INSERT INTO [Categories]
([CategoryName], [Description], [BrochurePath], [Picture])
VALUES
(@CategoryName, @Description, @BrochurePath, @Picture)
Layar akhir asisten meminta kita untuk memberi nama metode TableAdapter baru. Masukkan InsertWithPicture
dan klik Selesai.
Gambar 2: Beri nama Metode InsertWithPicture
TableAdapter Baru (Klik untuk melihat gambar ukuran penuh)
Langkah 2: Memperbarui Lapisan Logika Bisnis
Karena Lapisan Presentasi hanya boleh berinteraksi dengan Lapisan Logika Bisnis daripada melewatinya untuk langsung masuk ke Lapisan Akses Data, kita perlu membuat metode BLL yang memanggil metode DAL yang baru saja kita buat (InsertWithPicture
). Untuk tutorial ini, buat metode dalam kelas CategoriesBLL
bernama InsertWithPicture
yang menerima tiga String
dan sebuah array Byte
sebagai input. Parameter String
input digunakan untuk nama kategori, deskripsi, dan jalur file brosur, sedangkan array Byte
digunakan untuk konten biner dari gambar kategori. Seperti yang ditunjukkan oleh kode berikut, metode BLL ini memanggil metode DAL yang sesuai:
<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
Nota
Pastikan Anda telah menyimpan Typed DataSet sebelum menambahkan metode InsertWithPicture
ke BLL.
CategoriesTableAdapter
Karena kode kelas dibuat secara otomatis berdasarkan Himpunan Data Yang Dijenis, jika Anda tidak terlebih dahulu menyimpan perubahan Anda ke Kumpulan Data Yang Dijenis, Adapter
properti tidak akan tahu tentang metode tersebutInsertWithPicture
.
Langkah 3: Mencantumkan Kategori yang Ada dan Data Biner mereka
Dalam tutorial ini kita akan membuat halaman yang memungkinkan pengguna akhir untuk menambahkan kategori baru ke sistem, menyediakan gambar dan brosur untuk kategori baru. Dalam tutorial sebelumnya , kami menggunakan GridView dengan TemplateField dan ImageField untuk menampilkan setiap nama kategori, deskripsi, gambar, dan tautan untuk mengunduh brosurnya. Mari kita replikasi fungsionalitas tersebut untuk tutorial ini, membuat halaman yang mencantumkan semua kategori yang ada dan memungkinkan yang baru dibuat.
Mulailah dengan membuka halaman DisplayOrDownload.aspx
dari folder BinaryData
. Buka tampilan Sumber dan salin sintaks deklaratif GridView dan ObjectDataSource, menempelkannya dalam <asp:Content>
elemen di UploadInDetailsView.aspx
. Selain itu, jangan lupa juga untuk menyalin metode GenerateBrochureLink
dari kelas code-behind DisplayOrDownload.aspx
ke UploadInDetailsView.aspx
.
Gambar 3: Salin dan Tempel Sintaks Deklaratif dari DisplayOrDownload.aspx
ke UploadInDetailsView.aspx
(Klik untuk melihat gambar ukuran penuh)
Setelah menyalin sintaks dan GenerateBrochureLink
metode deklaratif ke UploadInDetailsView.aspx
halaman, lihat halaman melalui browser untuk memastikan bahwa semuanya disalin dengan benar. Anda akan melihat GridView yang mencantumkan delapan kategori yang menyertakan tautan untuk mengunduh brosur serta gambar kategori.
Gambar 4: Anda Sekarang Akan Melihat Setiap Kategori Bersama dengan Data Binernya (Klik untuk melihat gambar ukuran penuh)
Langkah 4: MengonfigurasiCategoriesDataSource
untuk Mendukung Penyisipan
CategoriesDataSource
ObjectDataSource yang Categories
digunakan oleh GridView saat ini tidak menyediakan kemampuan untuk menyisipkan data. Untuk mendukung penyisipan melalui kontrol data sumber ini, kita perlu memetakan metodenya Insert
ke metode dalam objek dasarnya, CategoriesBLL
. Secara khusus, kita ingin memetakan ini ke metode CategoriesBLL
yang kita tambahkan kembali di Langkah 2, InsertWithPicture
.
Mulailah dengan mengklik tautan Konfigurasi Sumber Data dari tag pintar ObjectDataSource. Layar pertama menunjukkan objek yang dikonfigurasi sumber data untuk bekerja dengan, CategoriesBLL
. Biarkan pengaturan ini as-is dan klik Berikutnya untuk melanjutkan ke layar Tentukan Metode Data. Pindahkan ke tab INSERT dan pilih InsertWithPicture
metode dari daftar drop-down. Klik Selesai untuk menyelesaikan wizard.
Gambar 5: Konfigurasikan ObjectDataSource untuk menggunakan InsertWithPicture
Metode (Klik untuk melihat gambar ukuran penuh)
Nota
Setelah menyelesaikan wizard, Visual Studio mungkin bertanya apakah Anda ingin Memperbarui Bidang dan Kunci, yang akan meregenerasi bidang kontrol Web pada data. Pilih Tidak, karena memilih Ya akan menimpa kustomisasi bidang apa pun yang mungkin telah Anda buat.
Setelah menyelesaikan wizard, ObjectDataSource sekarang akan menyertakan nilai untuk propertinya InsertMethod
serta InsertParameters
untuk empat kolom kategori, seperti yang diilustrasikan markup deklaratif berikut:
<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>
Langkah 5: Membuat Antarmuka Penyisipan
Seperti yang pertama kali dibahas dalam Gambaran Umum Menyisipkan, Memperbarui, dan Menghapus Data, kontrol DetailsView menyediakan antarmuka penyisipan bawaan yang dapat digunakan saat bekerja dengan kontrol sumber data yang mendukung penyisipan. Mari kita tambahkan kontrol DetailsView ke halaman ini di atas GridView yang akan merender antarmuka penyisipannya secara permanen, memungkinkan pengguna untuk dengan cepat menambahkan kategori baru. Setelah menambahkan kategori baru di DetailsView, GridView di bawahnya akan secara otomatis me-refresh dan menampilkan kategori baru.
Mulailah dengan menyeret DetailsView dari Kotak Alat ke Perancang di atas GridView, mengatur propertinya ID
ke NewCategory
dan menghapus nilai properti Height
dan Width
. Dari tag pintar DetailsView, ikat ke yang sudah ada CategoriesDataSource
lalu centang kotak centang Aktifkan Penyisipan.
Gambar 6: Ikat DetailsView ke CategoriesDataSource
dan Aktifkan Fungsi Penyisipan (Klik untuk melihat gambar ukuran penuh)
Untuk merender DetailsView secara permanen di antarmuka penyisipannya, atur propertinya DefaultMode
ke Insert
.
Perhatikan bahwa DetailsView memiliki lima BoundFields CategoryID
, CategoryName
, Description
, NumberOfProducts
, dan BrochurePath
meskipun CategoryID
BoundField tidak dirender dalam antarmuka penyisipan karena propertinya InsertVisible
diatur ke False
. BoundFields ini ada karena kolom-kolom tersebut adalah kolom yang dikembalikan oleh metode GetCategories()
, yang dieksekusi oleh ObjectDataSource untuk mengambil datanya. Namun, untuk menyisipkan, kami tidak ingin membiarkan pengguna menentukan nilai untuk NumberOfProducts
. Selain itu, kita perlu mengizinkan mereka mengunggah gambar untuk kategori baru serta mengunggah PDF untuk brosur.
NumberOfProducts
Hapus BoundField dari DetailsView sama sekali lalu perbarui HeaderText
properti CategoryName
dan BrochurePath
BoundFields ke Kategori dan Brosur, masing-masing. Selanjutnya, konversikan BrochurePath
BoundField menjadi TemplateField dan tambahkan TemplateField baru untuk gambar, memberi TemplateField baru ini nilai HeaderText
Gambar. Pindahkan Picture
TemplateField sehingga berada di BrochurePath
antara TemplateField dan CommandField.
Gambar 7: Mengikat DetailsView ke CategoriesDataSource
dan Mengaktifkan Penyisipan
Jika Anda mengonversi BrochurePath
BoundField menjadi TemplateField melalui kotak dialog Edit Bidang, TemplateField menyertakan ItemTemplate
, EditItemTemplate
, dan InsertItemTemplate
. Namun, hanya yang InsertItemTemplate
diperlukan, jadi jangan ragu untuk menghapus dua templat lainnya. Pada titik ini, sintaks deklaratif DetailsView Anda akan terlihat seperti berikut ini:
<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>
Menambahkan Kontrol FileUpload untuk Bidang Brosur dan Gambar
Saat ini, BrochurePath
TemplateFields InsertItemTemplate
berisi TextBox, sementara Picture
TemplateField tidak berisi templat apa pun. Kita perlu memperbarui kedua TemplateField ini InsertItemTemplate
untuk menggunakan kontrol FileUpload.
Dari tag pintar DetailsView, pilih opsi Edit Templat lalu pilih BrochurePath
TemplateFields InsertItemTemplate
dari daftar drop-down. Hapus Kotak Teks lalu seret kontrol FileUpload dari Kotak Alat ke dalam templat. Atur kontrol ID
FileUpload ke BrochureUpload
. Demikian pula, tambahkan kontrol FileUpload ke Picture
TemplateFields InsertItemTemplate
. Atur kontrol ID
FileUpload ini ke PictureUpload
.
Gambar 8: Tambahkan Kontrol FileUpload ke InsertItemTemplate
(Klik untuk melihat gambar ukuran penuh)
Setelah membuat penambahan ini, dua sintaks deklaratif TemplateField adalah:
<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>
Saat pengguna menambahkan kategori baru, kami ingin memastikan bahwa brosur dan gambar adalah jenis file yang benar. Untuk brosur, pengguna harus menyediakan PDF. Untuk gambar, kita memerlukan pengguna untuk mengunggah file gambar, tetapi apakah kita mengizinkan sembarang file gambar atau hanya file gambar dari jenis tertentu, seperti GIF atau JPG? Untuk memungkinkan jenis file yang berbeda, kita perlu memperluas Categories
skema untuk menyertakan kolom yang mengambil jenis file sehingga jenis ini dapat dikirim ke klien melalui Response.ContentType
di DisplayCategoryPicture.aspx
. Karena kita tidak memiliki kolom seperti itu, akan bijaksana untuk membatasi pengguna untuk hanya menyediakan jenis file gambar tertentu. Gambar Categories
tabel yang ada adalah bitmap, tetapi JPG adalah format file yang lebih sesuai untuk gambar yang disajikan melalui web.
Jika pengguna mengunggah jenis file yang salah, kita perlu membatalkan penyisipan dan menampilkan pesan yang menunjukkan masalah. Tambahkan kontrol Web Label di bawah DetailsView. Atur properti ID
ke UploadWarning
, hapus properti Text
, atur properti CssClass
ke Peringatan, dan atur properti Visible
serta EnableViewState
ke False
. Kelas Warning
CSS didefinisikan dalam Styles.css
dan merender teks dalam font besar, merah, miring, dan tebal.
Nota
Idealnya, CategoryName
dan Description
BoundFields akan dikonversi menjadi TemplateFields dan antarmuka penyisipan mereka disesuaikan. Antarmuka Description
penyisipan, misalnya, kemungkinan akan lebih tepat menggunakan kotak teks multibaris. Dan karena CategoryName
kolom tidak menerima NULL
nilai, RequiredFieldValidator harus ditambahkan untuk memastikan pengguna memberikan nilai untuk nama kategori baru. Langkah-langkah ini dibiarkan sebagai latihan kepada pembaca. Lihat kembali menyesuaikan Antarmuka Modifikasi Data untuk melihat secara mendalam penambahan antarmuka modifikasi data.
Langkah 6: Menyimpan Brosur yang Diunggah ke Sistem File Server Web
Saat pengguna memasukkan nilai untuk kategori baru dan mengklik tombol Sisipkan, akan terjadi postback dan alur kerja penyisipan dimulai. Pertama, peristiwa DetailsView ItemInserting
diaktifkan. Selanjutnya, metode ObjectDataSource dipanggil Insert()
, yang menghasilkan rekaman baru yang ditambahkan ke Categories
tabel. Setelah itu, peristiwa DetailsView ItemInserted
diaktifkan.
Sebelum metode ObjectDataSource dipanggil Insert()
, kita harus terlebih dahulu memastikan bahwa jenis file yang sesuai diunggah oleh pengguna lalu menyimpan PDF brosur ke sistem file server web. Buat pelaksana acara untuk kejadian DetailsView ItemInserting
dan tambahkan kode berikut:
' 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
Penanganan aktivitas dimulai dengan mereferensikan BrochureUpload
kontrol FileUpload dari templat DetailsView. Kemudian, jika brosur telah diunggah, ekstensi file s yang diunggah diperiksa. Jika ekstensi tidak .PDF, maka peringatan ditampilkan, sisipan dibatalkan, dan eksekusi penanganan aktivitas berakhir.
Nota
Mengandalkan ekstensi file yang diunggah bukanlah cara yang efektif untuk memastikan bahwa file yang diunggah adalah dokumen PDF. Pengguna dapat memiliki dokumen PDF yang valid dengan ekstensi .Brochure
, atau bisa saja mengambil dokumen non-PDF dan memberinya .pdf
ekstensi. Konten biner file harus diperiksa secara terprogram untuk memverifikasi jenis file secara lebih meyakinkan. Namun, pendekatan menyeluruh seperti itu seringkali berlebihan; memeriksa ekstensi cukup untuk sebagian besar skenario.
Seperti yang dibahas dalam tutorial Mengunggah File, perhatian harus diberikan saat menyimpan file ke sistem file sehingga unggahan seorang pengguna tidak menimpa unggahan pengguna lainnya. Untuk tutorial ini, kami akan mencoba menggunakan nama yang sama dengan file yang diunggah. Namun, jika sudah ada file di ~/Brochures
direktori dengan nama file yang sama, kami akan menambahkan angka di akhir hingga nama unik ditemukan. Misalnya, jika pengguna mengunggah file brosur bernama Meats.pdf
, tetapi sudah ada file bernama Meats.pdf
di ~/Brochures
folder , kita akan mengubah nama file yang disimpan menjadi Meats-1.pdf
. Jika itu ada, kita akan mencoba Meats-2.pdf
, dan sebagainya, sampai nama file unik ditemukan.
Kode berikut menggunakan File.Exists(path)
metode untuk menentukan apakah file sudah ada dengan nama file yang ditentukan. Jika demikian, ia terus mencoba nama file baru untuk brosur sampai tidak ada konflik yang ditemukan.
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
Setelah nama file yang valid ditemukan, file perlu disimpan ke sistem file dan nilai ObjectDataSource brochurePath``InsertParameter
perlu diperbarui sehingga nama file ini ditulis ke database. Seperti yang kita lihat kembali dalam tutorial Mengunggah File , file dapat disimpan menggunakan metode kontrol SaveAs(path)
FileUpload. Untuk memperbarui parameter brochurePath
ObjectDataSource, gunakan koleksi e.Values
.
' Save the file to disk and set the value of the brochurePath parameter
BrochureUpload.SaveAs(Server.MapPath(brochurePath))
e.Values("brochurePath") = brochurePath
Langkah 7: Menyimpan Gambar yang Diunggah ke Database
Untuk menyimpan gambar yang diunggah ke rekaman baruCategories
, kita perlu menetapkan konten biner yang diunggah ke parameter ObjectDataSource dalam peristiwa DetailsViewpicture
ItemInserting
. Namun, sebelum kita membuat tugas ini, kita harus terlebih dahulu memastikan bahwa gambar yang diunggah adalah JPG dan bukan beberapa jenis gambar lainnya. Seperti pada Langkah 6, mari kita gunakan ekstensi file gambar yang diunggah untuk memastikan jenisnya.
Meskipun tabel Categories
mengizinkan nilai NULL
untuk kolom Picture
, semua kategori saat ini memiliki gambar. Mari kita paksa pengguna untuk memberikan gambar saat menambahkan kategori baru melalui halaman ini. Kode berikut memeriksa untuk memastikan bahwa gambar telah diunggah dan memiliki ekstensi yang sesuai.
' 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
Kode ini harus ditempatkan sebelum kode dari Langkah 6 sehingga jika ada masalah dengan unggahan gambar, penanganan aktivitas akan dihentikan sebelum file brosur disimpan ke sistem file.
Dengan asumsi bahwa file yang sesuai telah diunggah, tetapkan konten biner yang diunggah ke nilai parameter gambar dengan baris kode berikut:
' Set the value of the picture parameter
e.Values("picture") = PictureUpload.FileBytes
Penanganan Acara LengkapItemInserting
Untuk kelengkapan, berikut adalah pengolah peristiwa ItemInserting
secara keseluruhan.
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
Langkah 8: MemperbaikiDisplayCategoryPicture.aspx
Halaman
Mari kita luangkan waktu sejenak untuk menguji antarmuka penyisipan dan ItemInserting
penanganan aktivitas yang dibuat selama beberapa langkah terakhir.
UploadInDetailsView.aspx
Kunjungi halaman melalui browser dan coba tambahkan kategori, tetapi hilangkan gambar, atau tentukan gambar non-JPG atau brosur non-PDF. Dalam situasi seperti ini, pesan kesalahan akan ditampilkan dan proses penyisipan akan dibatalkan.
Gambar 9: Pesan Peringatan Ditampilkan Jika Jenis File Tidak Valid Diunggah (Klik untuk melihat gambar ukuran penuh)
Setelah Anda memverifikasi bahwa halaman memerlukan gambar untuk diunggah dan tidak akan menerima file non-PDF atau non-JPG, tambahkan kategori baru dengan gambar JPG yang valid, biarkan bidang Brosur kosong. Setelah mengklik tombol Sisipkan, halaman akan melakukan postback, dan rekaman baru akan ditambahkan ke tabel Categories
dengan isi biner dari gambar yang diunggah disimpan langsung dalam database. GridView diperbarui dan menampilkan baris untuk kategori yang baru ditambahkan, tetapi, seperti yang ditunjukkan Gambar 10, gambar kategori baru tidak dirender dengan benar.
Gambar 10: Gambar Kategori Baru tidak Ditampilkan (Klik untuk melihat gambar ukuran penuh)
Alasan gambar baru tidak ditampilkan adalah karena DisplayCategoryPicture.aspx
halaman yang mengembalikan gambar kategori tertentu dikonfigurasi untuk memproses bitmap yang memiliki header OLE. Header 78 byte ini dihapus dari konten biner kolom Picture
setelah dikirim kembali ke klien. Tetapi file JPG yang baru saja kami unggah untuk kategori baru tidak memiliki header OLE ini; oleh karena itu, byte yang valid dan diperlukan sedang dihapus dari data biner gambar.
Karena sekarang ada bitmap dengan header OLE dan JPG di dalam tabel Categories
, kita perlu memperbarui DisplayCategoryPicture.aspx
sehingga melakukan penghilangan header OLE untuk delapan kategori asli dan mengabaikan penghilangan ini untuk catatan kategori yang lebih baru. Dalam tutorial berikutnya, kami akan memeriksa cara memperbarui gambar rekaman yang ada, dan kami akan memperbarui semua gambar kategori lama sehingga gambar tersebut adalah JPG. Namun, untuk saat ini, gunakan kode berikut dalam DisplayCategoryPicture.aspx
untuk menghapus header OLE hanya untuk delapan kategori awal tersebut.
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
Dengan perubahan ini, gambar JPG sekarang dirender dengan benar di GridView.
Gambar 11: Gambar JPG untuk Kategori Baru Dirender Dengan Benar (Klik untuk melihat gambar ukuran penuh)
Langkah 9: Menghapus Brosur di Hadapan Pengecualian
Salah satu tantangan penyimpanan data biner pada sistem file server web adalah bahwa ia memperkenalkan pemutusan hubungan antara model data dan data binernya. Oleh karena itu, setiap kali rekaman dihapus, data biner yang sesuai pada sistem file juga harus dihapus. Ini bisa berpengaruh saat memasukkan data, juga. Pertimbangkan skenario berikut: pengguna menambahkan kategori baru, menentukan gambar dan brosur yang valid. Setelah mengklik tombol Sisipkan, terjadi postback dan peristiwa DetailsView ItemInserting
diaktifkan, mengakibatkan brosur disimpan ke sistem file server web. Selanjutnya, metode Insert()
dari ObjectDataSource dipanggil, yang memanggil metode CategoriesBLL
dari kelas InsertWithPicture
, dan kemudian memanggil metode CategoriesTableAdapter
dari InsertWithPicture
.
Sekarang, apa yang terjadi jika database offline, atau jika ada kesalahan dalam INSERT
pernyataan SQL? Dengan jelas INSERT akan gagal, sehingga tidak ada baris kategori baru yang akan ditambahkan ke database. Tetapi kami masih memiliki file brosur yang diunggah yang berada di sistem file server web! File ini perlu dihapus jika terjadi pengecualian selama alur kerja penyisipan.
Seperti yang dibahas sebelumnya dalam Penanganan Pengecualian BLL- dan DAL-Level dalam tutorial Halaman ASP.NET , ketika pengecualian dilemparkan dari dalam kedalaman arsitektur, itu menggelegak melalui berbagai lapisan. Di Lapisan Presentasi, kita dapat menentukan apakah pengecualian telah terjadi dari peristiwa DetailsView.ItemInserted
Penanganan aktivitas ini juga menyediakan nilai ObjectDataSource s InsertParameters
. Oleh karena itu, kita dapat membuat penanganan aktivitas untuk ItemInserted
peristiwa yang memeriksa apakah ada pengecualian dan, jika demikian, menghapus file yang ditentukan oleh parameter ObjectDataSource:brochurePath
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
Ringkasan
Ada sejumlah langkah yang harus dilakukan untuk menyediakan antarmuka berbasis web untuk menambahkan rekaman yang menyertakan data biner. Jika data biner disimpan langsung ke database, kemungkinan Anda harus memperbarui arsitektur, menambahkan metode tertentu untuk menangani kasus di mana data biner sedang dimasukkan. Setelah arsitektur diperbarui, langkah berikutnya adalah membuat antarmuka penyisipan, yang dapat dicapai menggunakan DetailsView yang telah disesuaikan untuk menyertakan kontrol FileUpload untuk setiap bidang data biner. Data yang diunggah kemudian dapat disimpan ke sistem file server web atau ditetapkan ke parameter sumber data di penanganan aktivitas DetailsView ItemInserting
.
Menyimpan data biner ke sistem file memerlukan lebih banyak perencanaan daripada menyimpan data langsung ke dalam database. Skema penamaan harus dipilih dengan cermat untuk menghindari unggahan satu pengguna menggantikan unggahan pengguna lain. Selain itu, langkah tambahan harus diambil untuk menghapus file yang diunggah jika penyisipan database gagal.
Kami sekarang memiliki kemampuan untuk menambahkan kategori baru ke sistem dengan brosur dan gambar, tetapi kami belum melihat cara memperbarui data biner kategori yang ada atau cara menghapus data biner dengan benar untuk kategori yang dihapus. Kita akan menjelajahi dua topik ini dalam tutorial berikutnya.
Selamat Pemrograman!
Tentang Penulis
Scott Mitchell, penulis tujuh buku ASP/ASP.NET dan pendiri 4GuysFromRolla.com, telah bekerja sama dengan teknologi Microsoft Web sejak 1998. Scott bekerja sebagai konsultan, pelatih, dan penulis independen. Buku terbarunya adalah Sams Teach Yourself ASP.NET 2.0 dalam 24 Jam. Dia dapat dijangkau di mitchell@4GuysFromRolla.com.
Ucapan terima kasih khusus kepada
Seri tutorial ini ditinjau oleh banyak peninjau yang bermanfaat. Peninjau utama untuk tutorial ini adalah Dave Gardner, Teresa Murphy, dan Bernadette Leigh. Tertarik untuk meninjau artikel MSDN saya yang akan datang? Jika demikian, hubungi saya di mitchell@4GuysFromRolla.com.