將圖片插入數據庫并使用asp.net讀取出來的正確方法
2024-07-10 12:57:36
供稿:網友
 
將圖片插入數據庫并使用asp.net讀取出來的正確方法
 
書寫本文是因為今天見到csdn的首頁上一篇存在明顯失誤的名為“在asp.net中從sqlserver檢索(retrieve)圖片”的文章。不說其錯誤是因為用其方法確實能從數據庫中讀取出圖片并顯示在瀏覽器,說其失誤是因為代碼的意圖不能被完全的實現,作者也似乎對http協議以及瀏覽器在處理http數據的流程一知半解。
 
1、如何出錯
以下是這片文章提到的方法:
public sub page_load(sender as object, e as eventargs)
 dim myconnection as new sqlconnection(configurationsettings.appsettings("connectionstring"))
 dim mycommand as new sqlcommand("select * from person", myconnection)
 try
 myconnection.open()
 dim mydatareader as sqldatareader 
 mydatareader = mycommand.executereader(commandbehavior.closeconnection)
 do while (mydatareader.read())
 response.contenttype = mydatareader.item("personimagetype")
 response.binarywrite(mydatareader.item("personimage"))
 loop
 myconnection.close()
 response.write("person info successfully retrieved!")
 catch sqlexc as sqlexception
 response.write("read failed : " & sqlexc.tostring())
 end try
 end sub
顯然,編程者是想將person表中所有的記錄中的personimage字段所存儲的圖片一次性地輸出到瀏覽器中,并且在輸出成功地情況下在已輸出的圖片的下方打印出“person info successfully retrieved!”信息。然而事實上上述代碼僅僅能正確地輸出第一條記錄中的圖片。對于瀏覽器來說,一個http請求獲取一個文件(html或者圖片),所以以上代碼的輸出將被作為一個文件(類型依據response.contenttype = mydatareader.item("personimagetype")定)被瀏覽器處理。如果http相應的類型是image/jpeg之類的圖片,則瀏覽器使用相應的圖片解析功能對這一個圖片文件進行解析。因此,上述代碼的顯示結果只能是第一條記錄personimage字段的圖片。后面的記錄輸出的圖片數據將成為第一張圖片的多余數據(此點具有普遍性,但并非絕對,依圖片的格式而定),從而后面的“person info successfully retrieved!”的信息也自然無法本顯示出來,因為這些信息已經是圖片文件里面的編碼了。
 
2、正確的做法
a、將圖片輸入到數據庫中,以下是一個將圖片輸入到數據庫的代碼片斷:(完整的demo程序見附錄一)
 filestream fs=file.openread(filepath.text);
 byte[] content=new byte[fs.length];
 fs.read(content, 0,content.length);
 fs.close();
 
 sqlconnection conn=new sqlconnection("integrated security=sspi;persist security info=false;initial catalog=databaseimage;data source=(local)");
 conn.open();
 
 sqlcommand comm=conn.createcommand();
 comm.commandtext="insert into images(image, contenttype) values(@image, @contenttype)";
 comm.commandtype=commandtype.text;
 
 comm.parameters.add("@image", sqldbtype.image).value=content;
 comm.parameters.add("@contenttype", sqldbtype.nvarchar).value=
 getcontenttype(new fileinfo(filepath.text).extension.remove(0,1));
 
 if(comm.executenonquery()==1)
 {
 messagebox.show("successfully insert image into database!");
 }
 else
 {
 messagebox.show("failed to insert image into database");
 }
 
 conn.close();
 
b、將數據庫中的圖片讀出來的代碼片斷:(完整demo程序見附錄二)
 try{
 sqlconnection conn=new sqlconnection("integrated security=sspi;persist security info=false;initial catalog=databaseimage;data source=(local)");
 conn.open();
 
 sqlcommand comm=conn.createcommand();
 comm.commandtext="select * from images where [email protected]";
 comm.commandtype=commandtype.text;
 
 comm.parameters.add("@id", sqldbtype.bigint).value=int.parse(request["id"]);
 
 sqldatareader reader=comm.executereader();
 while(reader.read())
 {
 response.contenttype=reader["contenttype"].tostring();
 response.binarywrite((byte[])reader["image"]);
 }
 response.end();
 
 conn.close();
 }
 catch
 {
 response.end();
 }
這段代碼可置于page_load事件中,數據圖片要注意的兩點是:
一、 設置正確的contenttype(http中的content-type),圖片的content-type格式一般為image/*,如jpeg為image/jpeg,bmp為image/bmp等等。
二、 僅僅輸出一張圖片二進制流,asp.net 中page_load事件先于頁面輸出被觸發,因此圖片的輸出可以在此事件中進行,直接操作reponse對象,避免輸出與圖片無關的而外信息(額外的第二張圖片或者文字)。圖片的二進制流輸出后及時使用response.end()方法結束http響應,避免頁面中的額外信息被asp.net的引擎默認輸出到客戶端。
 
希望此文能夠起到拋磚引玉的作用!^_^
 
附錄一:
mainform.cs
using system;
using system.drawing;
using system.collections;
using system.componentmodel;
using system.data;
using system.data.sqlclient;
using system.io;
using system.windows.forms;
 
namespace insertimagetodatabase
{
 public class mainform : system.windows.forms.form
 {
 private system.windows.forms.openfiledialog openfiledlg;
 private system.windows.forms.textbox filepath;
 private system.windows.forms.button browsebutton;
 private system.windows.forms.button insertbutton;
 /// <summary>
 /// required designer variable.
 /// </summary>
 private system.componentmodel.container components = null;
 
 public mainform()
 {
 //
 // required for windows form designer support
 //
 initializecomponent();
 
 //
 // todo: add any constructor code after initializecomponent call
 //
 }
 
 /// <summary>
 /// clean up any resources being used.
 /// </summary>
 protected override void dispose( bool disposing )
 {
 if( disposing )
 {
 if (components != null) 
 {
 components.dispose();
 }
 }
 base.dispose( disposing );
 }
 
 #region windows form designer generated code
 /// <summary>
 /// required method for designer support - do not modify
 /// the contents of this method with the code editor.
 /// </summary>
 private void initializecomponent()
 {
 this.openfiledlg = new system.windows.forms.openfiledialog();
 this.filepath = new system.windows.forms.textbox();
 this.browsebutton = new system.windows.forms.button();
 this.insertbutton = new system.windows.forms.button();
 this.suspendlayout();
 // 
 // openfiledlg
 // 
 this.openfiledlg.defaultext = "*.jpg;*.gif;*.bmp;*.png";
 this.openfiledlg.filter = "image files|*.jpg;*.gif;*.bmp;*.png|all files|*.*";
 // 
 // filepath
 // 
 this.filepath.location = new system.drawing.point(16, 16);
 this.filepath.name = "filepath";
 this.filepath.readonly = true;
 this.filepath.size = new system.drawing.size(168, 20);
 this.filepath.tabindex = 0;
 this.filepath.text = "";
 // 
 // browsebutton
 // 
 this.browsebutton.location = new system.drawing.point(200, 16);
 this.browsebutton.name = "browsebutton";
 this.browsebutton.tabindex = 1;
 this.browsebutton.text = "&browse";
 this.browsebutton.click += new system.eventhandler(this.browsebutton_click);
 // 
 // insertbutton
 // 
 this.insertbutton.enabled = false;
 this.insertbutton.location = new system.drawing.point(200, 56);
 this.insertbutton.name = "insertbutton";
 this.insertbutton.tabindex = 2;
 this.insertbutton.text = "&insert";
 this.insertbutton.click += new system.eventhandler(this.insertbutton_click);
 // 
 // mainform
 // 
 this.autoscalebasesize = new system.drawing.size(5, 13);
 this.clientsize = new system.drawing.size(292, 273);
 this.controls.add(this.insertbutton);
 this.controls.add(this.browsebutton);
 this.controls.add(this.filepath);
 this.formborderstyle = system.windows.forms.formborderstyle.fixedsingle;
 this.maximizebox = false;
 this.name = "mainform";
 this.text = "insert image to database";
 this.resumelayout(false);
 
 }
 #endregion
 
 /// <summary>
 /// the main entry point for the application.
 /// </summary>
 [stathread]
 static void main() 
 {
 application.run(new mainform());
 }
 
 private void browsebutton_click(object sender, system.eventargs e)
 {
 if(openfiledlg.showdialog()==dialogresult.ok)
 {
 filepath.text=openfiledlg.filename;
 insertbutton.enabled=true;
 }
 }
 
 private void insertbutton_click(object sender, system.eventargs e)
 {
 filestream fs=file.openread(filepath.text);
 byte[] content=new byte[fs.length];
 fs.read(content, 0,content.length);
 fs.close();
 
 sqlconnection conn=new sqlconnection("integrated security=sspi;persist security info=false;initial catalog=databaseimage;data source=(local)");
 conn.open();
 
 sqlcommand comm=conn.createcommand();
 comm.commandtext="insert into images(image, contenttype) values(@image, @contenttype)";
 comm.commandtype=commandtype.text;
 
 sqlparameter param=comm.parameters.add("@image", sqldbtype.image);
 param.value=content;
 comm.parameters.add("@contenttype", sqldbtype.nvarchar).value=
 getcontenttype(new fileinfo(filepath.text).extension.remove(0,1));
 
 if(comm.executenonquery()==1)
 {
 messagebox.show("successfully insert image into database!");
 }
 else
 {
 messagebox.show("failed to insert image into database");
 }
 
 conn.close();
 }
 
 private string getcontenttype(string extension)
 {
 string type="jpeg";
 if(extension=="jpg")
 {
 type="jpeg";
 }else
 {
 type=extension;
 }
 return "image/"+type;
 }
 }
}
 
附錄二:
readimage.aspx
<%@ page language="c#" codebehind="readimage.aspx.cs" autoeventwireup="false" inherits="readimage.readimage"%>
readimage.aspx.cs
using system;
using system.collections;
using system.componentmodel;
using system.data;
using system.data.sqlclient;
using system.drawing;
using system.web;
using system.web.sessionstate;
using system.web.ui;
using system.web.ui.webcontrols;
using system.web.ui.htmlcontrols;
 
namespace readimage
{
 /// <summary>
 /// summary description for readimage.
 /// </summary>
 public class readimage : system.web.ui.page
 {
 private void page_load(object sender, system.eventargs e)
 {
 try{
 sqlconnection conn=new sqlconnection("integrated security=sspi;persist security info=false;initial catalog=databaseimage;data source=(local)");
 conn.open();
 
 sqlcommand comm=conn.createcommand();
 comm.commandtext="select * from images where id>@id";
 comm.commandtype=commandtype.text;
 
 comm.parameters.add("@id", sqldbtype.bigint).value=int.parse(request["id"]);
 
 sqldatareader reader=comm.executereader();
 while(reader.read())
 {
 response.contenttype=reader["contenttype"].tostring();
 response.binarywrite((byte[])reader["image"]);
 }
 response.write("aaaaaa");
 response.end();
 
 conn.close();
 }
 catch
 {
 response.end();
 }
 }
 
 #region web form designer generated code
 override protected void oninit(eventargs e)
 {
 //
 // codegen: this call is required by the asp.net web form designer.
 //
 initializecomponent();
 base.oninit(e);
 }
 
 /// <summary>
 /// required method for designer support - do not modify
 /// the contents of this method with the code editor.
 /// </summary>
 private void initializecomponent()
 { 
 this.load += new system.eventhandler(this.page_load);
 
 }
 #endregion
 }
}