Lưu hình ảnh vào database
Trong bài viết này tôi sẽ hướng dẫn bạn cách chèn hình ảnh trực tiếp vào database. Cách này tuy làm cho database lớn/nặng nhưng nó cũng giải quyết rất nhiều vấn đề trong quá trình lập trình.
Ở đây, csdl tôi sử dụng là ms Access và MS SQLserver.
Cách 1: Database là Access
1. Bạn tạo 1 file access có tên TestDB.mdb nằm trong thư mục bin\debug của ứng dụng(chỗ khác cũng không sao, tùy).Tạo 1 bảng có tên tblSinhvien có cấu trúc như sau:
Tên field | Kiểu dữ liệu |
---|---|
MSSV | Text(15) |
hinhAnh | OLE Object |
2. Tạo 1 Windows Form Application Project có tên Store_Retrieve_Image_From_DB.
3. Tạo lớp có tên ConnectDB.cs với nội dung sau:
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Data.OleDb;namespace Store_Retrieve_Image_From_DB { public class ConnectDB { private OleDbConnection con; private DataSet ds; private OleDbDataAdapter daSV; /// <summary> /// Phương thức constructor khởi tạo kết nối đến database /// </summary> public ConnectDB() { try { con = new OleDbConnection(); con.ConnectionString = “Provider=microsoft.jet.OLEDB.4.0;Data Source=”+ System.Windows.Forms.Application.StartupPath+”\\TestDB.mdb”; con.Open(); } catch (Exception) { throw; } } /// <summary> /// Lấp về tất cả các mẫu tin trong bảng tblSinhvien /// </summary> /// <returns></returns> public DataSet GetTable() { ds = new DataSet(); daSV = new OleDbDataAdapter(“select * from tblSinhvien”, con); daSV.Fill(ds, “tblSinhvien”); return ds; } /// <summary> /// Cập nhật các thay đổi của người dùng /// </summary> public void UpdateSV() { try { OleDbCommandBuilder bd = new OleDbCommandBuilder(daSV); daSV.Update(ds, “tblSinhvien”); } catch (Exception) { throw; |
Lớp này dùng để đọc dữ liệu từ database cũng như cập nhật dữ liệu xuống database.
3. Thiết kế MainForm như hình
4. Code cho Form:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Windows.Forms;namespace Store_Retrieve_Image_From_DB { public partial class MainForm : Form { private ConnectDB conDB; private DataSet ds = new DataSet(); private BindingSource bs; private DataTable dtSV; public MainForm() } private void MainForm_Load(object sender, EventArgs e) private void btnLuu_Click(object sender, EventArgs e) Byte[] bytBLOBData = new Byte[ms.Length]; conDB.UpdateSV(); private void btnLoadHinh_Click(object sender, EventArgs e) |
Chú ý:
Để đọc dữ liệu hình ảnh ra ta dùng 1 mảng Byte để chứa giá trị của field hình ảnh. Sau đó muốn hiển thị nó lên PictureBox ta phải dùng MemoryStream để đưa ra:
Byte[] i = (byte[])row["hinhAnh"];
MemoryStream stmBLOBData = new MemoryStream(i);
picHinhAnh.Image = Image.FromStream(stmBLOBData);
Để cập nhật dữ liệu vào db, ta phải lấy ảnh từ PictureBox vào 1 MemoryStream:
MemoryStream ms = new MemoryStream();
picHinhAnh.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
Rồi sau đó mới chuyển nó thành mảng Byte rồi cung cấp cho 1 datarow để update xuống database.
Byte[] bytBLOBData = new Byte[ms.Length];
ms.Position = 0;
ms.Read(bytBLOBData, 0, Convert.ToInt32(ms.Length));
dr["hinhAnh"] = bytBLOBData;
dtSV.Rows.Add(dr);
Chạy ứng dụng, kết quả như hình sau:
Cách 2: Database là Microsoft SQL Server
1. Tạo database có tên: TestImageDB với 1 bảng có tên tblImages và có cấu trúc như hình sau:
2. Tạo stored project có tên InsertImage với sql script như sau:
CREATE PROCEDURE InsertImage @filename nvarchar(250), @blobdata image AS insert into tblImages values( @filename, @blobdata ) |
3. Tạo Windows Form Application Project có tên AnotherWay.
4. Tạo lớp ConnectDB.cs có nội dung như sau:
using System; using System.Collections.Generic; using System.IO; using System.Data; using System.Data.SqlClient; namespace AnotherWay public ConnectDB() public void StorePicture(string filename) public byte[] RetrieveImage() using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) |
5. Thiết kế Form như hình
6. Code cho Form:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Windows.Forms; namespace AnotherWay private void button1_Click(object sender, EventArgs e) private void button2_Click(object sender, EventArgs e) |
7. Thực thi
Trước hết nhấn nút Lưu, sau đó muốn xem lại mẫu tin đã lưu, nhấn nút load.
Chúc thành công!
bini said
Có thể cung cấp code của việc ứng dụng lưu ảnh vào cở sở dữ liệu nhnwg khi lấy ảnh ra ta nạp vào một ảnh mới và so sánh nó có giồng với ảnh cũ trong cở sở dữ liệu hay ko,hay nói cách khác là một dạng tìm kiếm ảnh vậy
Bảo Trung said
Thưa thầy, vấn đề thầy nói ở bài này đúng là vấn đề em cần. Nhưng khổ 1 nỗi là em không thể đưa hình trực tiếp vào DB được vì yêu cầu dung lượng DB phải bé thôi, thế nên em trong cột Images của DB em chỉ điền Path vào. Bây giờ làm thế nào để load động được lên picture box đây hả thầy. Vấn đề là không được dùng đường dẫn tuyệt đối được ạh. Thầy gỡ giúp em với được không ạh. Cám ơn thầy nhiều.
Bao Trung said
Sao thay ko tra loi thay oi
vovanhai said
cái này bạn tự tìm hiểu nhé. Tôi e rằng tôi k có thời gian! Sorry.
vovanhai said
Thì copy image vào thư mục chứa file exe của ứng dụng rồi dùng Application.getStartupPath().
bao long said
<%–
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
namespace UploadFile
{
///
/// Summary description for WebForm1.
///
public class WebForm1 : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button cmdUpload;
protected System.Web.UI.WebControls.Label lblInfo;
protected System.Web.UI.HtmlControls.HtmlInputFile FileInput;
private void Page_Load(object sender, System.EventArgs e)
{
// Only accept image types.
FileInput.Accept = “image/*”;
}
#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);
}
///
/// Required method for Designer support – do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.cmdUpload.Click += new System.EventHandler(this.cmdUpload_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void cmdUpload_Click(object sender, System.EventArgs e)
{
if (FileInput.PostedFile.FileName == “”)
{
lblInfo.Text = “No file specified.”;
}
else
{
try
{
string serverFileName = Path.GetFileName(FileInput.PostedFile.FileName);
//FileInput.PostedFile.SaveAs(@”c:\” + serverFileName);
FileInput.PostedFile.SaveAs(MapPath(“.”) + serverFileName);
lblInfo.Text = “File ” + serverFileName;
lblInfo.Text += ” uploaded successfully.”;
}
catch (Exception err)
{
lblInfo.Text = err.Message;
}
}
}
}
}
–%>
bao long said
Bạn xem thử nhé!
bao long said
Nếu bạn cảm thấy chưa chi tiết thì bạn có thể xem tại đây nhé!
http://vaolamgi.com/diendan/forum_posts.asp?TID=60
Cuong Nguyen said
Em đã làm theo hướng dẫn của thầy. Dịch không có lỗi. Nhưng khi chạy chương trình có thông báo lỗi sau, dù file ảnh <30KB:
System.Data.SqlClient.SqlException: String or binary data would be truncated.
Trước đó,em có làm một ví dụ nhỏ về lưu trữ ảnh và cũng xuất hiện thông báo trên.
Thầy và các bạn có biết cách khắc phục chỉ giùm em nhé.
Lê duy Dũng said
bạn thử dùng đoạn này xem được ko nhé Cuong Nghuen
string getimg()
{
try
{
//Thumbnail th = new Thumbnail();
//RootPath = CSContext.SRootDir + "\\images\\adv";
RootPath = HttpContext.Current.Request.PhysicalApplicationPath + "\\resource\\logonews";
Log.info("RootPath:" + RootPath);
//string spath = (string)Session["PATHTEMP"];
if (imgAdv.PostedFile != null && imgAdv.PostedFile.FileName.Length != 0) //Checking for valid file
{
// Since the PostedFile.FileNameFileName gives the entire path we use Substring function to rip of the filename alone.
string StrFileNameType = imgAdv.PostedFile.FileName.Substring(imgAdv.PostedFile.FileName.LastIndexOf(".") + 1);
StrFileName = DateTime.Now.Ticks.ToString() + "." + StrFileNameType;
string StrFileType = imgAdv.PostedFile.ContentType;
int IntFileSize = imgAdv.PostedFile.ContentLength;
if (IntFileSize 3145728)
{
return StrFileName = txtmn.Text;
} //error.Text = "upload failed";
else
{
imgAdv.PostedFile.SaveAs(RootPath + "\\" + StrFileName);
//th.GenerateThumbnail(StrFileName, "~/resource/logonews/", "m" + StrFileName, 101);
return StrFileName;
}
}
else
{
return StrFileName = txtmn.Text;
}
}
catch (Exception ex)
{
Log.info("KHONG LAY THU MUC NAY " + ex.Message);
return StrFileName;
}
}
chúc bạn thành công
tinhspt said
thầy có thể demo một bài bằng java được không thầy, chân thành cảm ơn thầy
hoadienanh said
e làm hoài lấy dữ liệu từ datetimepicker mãi mà toàn lỗi.
//createDate lấy từ VO class (return và get)
VO.createDate = Convert.ToDateTime(dtCrDate.Text.ToString());
hoặc
VO.createDate = dtCrDate.Value;
trong CDQL e khai báo kiểu dateitme bình thường
Mong thầy chỉ bảo!
vovanhai said
Em coi lại định dạng ngày tháng của em sao đã.
Nguyen Duc Tung said
Cảm ơn thầy nhiều.!
Nguyen Van Sang said
Đó là ngôn ngữ C#, còn lở là ngôn ngữ Java thì phải làm sao, thầy ơi hướng dẫn cho em với. Và hình như là Java không làm được chuyện này phải không thầy, em tìm khắp trên mạng chi toàn cho ngôn ngữ C# thôi chớ Java thì không thấy cái nào hết.
Võ Văn Hải said
Xem ở đây: Ví dụ
Thanhle said
Thầy cho em hỏi là muốn upload video thì như thế nào? Có giống với hình ảnh ko?
Nếu ko anh cho em cơ chế mà người ta hay dùng như các trang facebook hay zing chẳng hạn.
Em hỏi thêm câu nữa là cách lưu hình vào database này có phải là cách làm phổ biến không? Thông thường các website lưu hình ảnh làm theo cách nào !
Thanks thầy !
Võ Văn Hải said
Về cơ bản thì giống nhau. Trong Facebook hay Zing hay các trang web, hình ảnh sẽ không được lưu vào DB, thay vào đó người ta lưu image path rồi load.
Thanhle said
Cám ơn thầy nhiều ạ !
Phan Thanh Vũ said
cảm ơn thầy
anhtuan21204 said
cho em hỏi cái panel để load hình lên khi click vào datagridview là gì vậy.
Võ Văn Hải said
là picturebox.
hi hi said
String or binary data would be truncated.
The statement has been terminated.
nó báo lỗi như vậy giải quyết sao ạ?
Võ Văn Hải said
Chiều dài(độ lớn) của chuỗi hoặc dữ liệu dạng nhị phân bị cắt bớt(trường dữ liệu nhỏ quá, lưu không đủ).
bin said
cảm ơn anh nhiều. ^^
xemnhadat said
Cảm ơn anh rất nhiều, trước em nghĩ là chỉ nên lưu đường dẫn ảnh vào database mà thôi.
Huỳnh Văn Thịnh said
Thưa thầy, em chạy nó báo
The name ‘stmBLOBData’ does not exist in the current context
The type or namespace name ‘MemoryStream’ could not be found (are you missing a using directive or an assembly reference?)
là thế nào vậy thầy. Mong thầy giúp em.
Võ Văn Hải said
“The name ‘stmBLOBData’ does not exist in the current context
The type or namespace name ‘MemoryStream’ could not be found (are you missing a using directive or an assembly reference?)”
Em có using thư viện System.IO chưa vậy? Thêm nữa, phiên bản thầy sử dụng là VS2008
STYE4U said
Sao lại lưu ảnh vào DB, tiện cho lập trình nhưng load rất nặng, nhỡ khi server có vấn đề mà backup chưa kịp thì tiêu file luôn. Nếu website nhỏ thì lưu hình ở webhos, nếu site lớn thì sử dụng dịch vụ lưu ảnh trugn gian hoặc thuê thêm host tạo subdomain mà chứa.
Dương Tấn Biên said
sao ko ai pót demo chuong trinh lên vậy
do cong thang said
thay oi Thay Code Load Image Len DataGridview Su dung Linq Va SQL 2005 ko thay neu co thay cho em xin hay ban demo thi cang tot <>
ds said
thầy ơi thầy làm thêm nút sửa và nút xóa đi. em không biết làm chác nào để có thể thay được cái ảnh khác
Nguyễn Phạm Diễm Hằng said
cảm ơn thầy nhìu ạ…
caovantuan said
Em chào thầy! Thầy ơi cho em hỏi với em muốn lưu đường dẫn hình xuống database sau đó em chỉ load lên vậy phải làm thế nào ah, em định lưu đường dẫn hình sử dụng LinQ và WCF mà 2 cái đó em chưa có rành lắm. Em mong thầy cố gắng chỉ giúp em với ạ. Em cám ơn Thầy nhiều nhiều
Tiến thành said
Cho em hỏi với ạ ,em lại muốn gán ảnh động vào node trong cây treeview thì em phải làm thể nào ạ ,em lưu đc ảnh vào trong CSDL rồi ạ , có phải thông qua Imagelist ko ạ , em ko gán đc trực tiếp kiểu picturebox bởi nó ko có thuộc tính .Image . Vậy fai lsao ạ .
thanh-kttv said
Bây h em muốn hiển thị ảnh đã được lưu vào trong CSDL đó lên các node trong cây treeview thì em fai làm tnao ạ