Bagikan melalui


Menyertakan Opsi Unggah File Saat Menambahkan Rekaman Baru (VB)

oleh Scott Mitchell

Unduh PDF

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: MenambahkanInsertWithPictureMetode keCategoriesTableAdapter

Ketika kami membuat CategoriesTableAdapter kembali dalam tutorial Membuat Lapisan Akses Data , kami mengonfigurasinya untuk secara otomatis menghasilkan INSERTpernyataan , 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.

Pilih Opsi INSERT

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.

Berikan nama 'InsertWithPicture' kepada metode TableAdapter baru

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.

Salin dan Tempel Sintaks Deklaratif dari 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.

Anda Sekarang Akan Melihat Setiap Kategori Bersama dengan Data Binernya

Gambar 4: Anda Sekarang Akan Melihat Setiap Kategori Bersama dengan Data Binernya (Klik untuk melihat gambar ukuran penuh)

Langkah 4: MengonfigurasiCategoriesDataSourceuntuk 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.

Mengonfigurasi ObjectDataSource untuk menggunakan Metode InsertWithPicture

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.

Cuplikan layar DetailsView dengan properti CategoryID diatur ke NewCategory, nilai properti Tinggi dan Lebar kosong, dan kotak centang Aktifkan Penyisipan dipilih.

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.

Cuplikan layar memperlihatkan jendela bidang dengan TemplateField, Picture, dan HeaderText disorot.

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.

Menambahkan Kontrol FileUpload ke InsertItemTemplate

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 DetailsViewpictureItemInserting. 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.aspxHalaman

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.

Pesan Peringatan Ditampilkan Jika Tipe File Tidak Valid Diunggah

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 Kategori Baru tidak Ditampilkan

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 JPG untuk Kategori Baru dirender dengan Benar

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.