其實將圖片儲存在資料庫中不外乎兩種方式。
1,圖片檔案儲存在硬碟上,資料庫中負責記錄路徑(不管是絕對路徑還是相對路徑)。
2,圖片直接以二進位的形式儲存在資料庫中。
兩者各有優勢
1,儲存的檔案顯而易見,而且實現方便。當然掉包也方便。
麻煩的地方就是管理,比如路徑以及關聯內容的識別管理。程式移植不變。
2,管理方便。全sql管理。圖片檔案及其相關的內容可以方便檢索和識別。
不便就是寫程式麻煩一點。當然這一點在現在來說,也是不值得一提。封裝好的庫包不需要再動腦筋想事。
還有就是當圖片檔案大和非常多的時候,將可能嚴重影響資料庫的效能。
當然還有很多異同都可以自己體會,具體選擇哪種方式,依據自身情況而定。
下面說說二進位儲存的例子。
在將圖片檔案添加到資料庫的時候,需要預先處理一下。
1,將圖片檔案轉換成二進位
2, 對二進位分析,提取檔案資料,剔除頭部和尾部
3, 然後就可以將位元據儲存在對應的image類型的欄位中了。
讀取圖片資料的時候,指定一下檔案格式。圖片就還原了。
這是一段n久前寫的vb代碼:
這段是頁面上傳圖片檔案的處理過程。request是form過來的。
formsize=request.totalbytes<br /> if formsize>500000 then<br /> response.write "<mce:script language='javascript'><!--<br />alert('只允許不大於500k的圖片上傳');<br />// --></mce:script>"<br /> response.write "<mce:script language='javascript'><!--<br />history.go(-1);<br />// --></mce:script>"<br /> end if<br /> formdata=request.binaryread(formsize)<br /> bncrlf=chrb(13) & chrb(10)<br /> divider=leftb(formdata,clng(instrb(formdata,bncrlf))-1)<br /> datastart=instrb(formdata,bncrlf & bncrlf)+4<br /> dataend=instrb(datastart+1,formdata,divider)-datastart<br /> mydata=midb(formdata,datastart,dataend)</p><p> Sql="Select * From test_img Where id =2"<br /> Rs.open sql,conn,1,3<br /> '追加資料到資料庫<br /> Rs.AddNew<br /> Rs("img").appendchunk mydata<br /> Rs.Update<br /> '閉和釋放對象<br /> Rs.close<br /> 'conn.close<br />
又興趣的可以研究下,不進行處理,資料庫中的相應欄位存放的內容是什麼,然後在看看處理後,欄位存放的二進位代碼內容又有什麼差異。
讀取的時候:
function getSignature(id)
set rs=server.createobject("ADODB.recordset")
sql="select * from test_img where id=" & id
rs.open sql,conn,1,1
'Response.ContentType = "text/html" '顯示圖片的格式也可以用
Response.ContentType = "image/gif"' 以gif顯示
'Response.ContentType = "image/jpg" '以jpg顯示
Response.BinaryWrite rs("img") '顯示圖片
rs.close
end function
Java版本的處理過程。
File file = new File("img.gif");<br />FileInputStream fis;</p><p>fis = new FileInputStream(file);<br />pstmt = conn<br />.prepareStatement("insert into tbl_image values (?,?)");<br />pstmt.setString(1, file.getName());<br />pstmt.setBinaryStream(2, fis, (int)file.length());<br />pstmt.executeUpdate();<br />pstmt.close();<br />fis.close();
這裡需要注意 pstmt.setBinaryStream(2,fis,(int)file.length) 需要加(int)。 很奇怪的。
沒有強制轉換,居然能報錯。雖然file.length()返回的是long。抑或sun還需要在加個函數setBinaryStream(int,InputStream,long)重載一下。
Exception in thread "main" java.lang.AbstractMethodError: com.microsoft.jdbc.base.BasePreparedStatement.setBinaryStream(ILjava/io/InputStream;J)V
為什麼這段Java代碼沒有預先處理呢,只能歸功於java.sql中已經實現了,我們就隨便用就行了。
再補充一個例子的二進位檔案:
這個是圖片檔案儲存體到資料庫中的二進位表示形式:
0x47494638396123001E00E60000000000FFFFFFFEFEFEFDFDFDF7F7F7F2F2F2EFEFEFEEEEEEEDEDEDEAEAEADEDEDEDBDBDBDADADAD9D9D9CECECECBCBCBC8C8C8C5C5C5B8B8B8B7B7B7B2B2B2AFAFAFA7A7A7A6A6A6A1A1A1A0A0A09F9F9F9999999494949393938F8F8F8D8D8D8C8C8C8989898787878181817C7C7C7878787474747373736F6F6F6C6C6C6767676666666161615F5F5F5C5C5C5B5B5B5A5A5A5959595858585454545353534D4D4D4C4C4C4040403C3C3C3636362E2E2E2D2D2D2929292727272020201F1F1F1D1D1D1818181616161414141313130F0F0F0C0C0C0B0B0B0A0A0A080808070707040404FFFFFF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021F9040100004C002C0000000023001E000007FF804C82838485868788018A8B8C8D8E8F8D4C90014100963593990192900F002632009A939C8D968A1F01A2A38FA58CA7130036AC90AE96B7AAABB48AA79BAA11B7A296088D1ABA900018AB4CC1129A431E9A0201268A4CC4B74999000D001093410139D6BC3014058F03C29617C8A2EABE013FBD002A0C1D8A30B8C78C3EA707A25C2D0AC60BC00E01FC3E04034042119078A67ABDA2C148C929002044F1083003E2A21112070240F2CA920E61B94A780C702264417E1B2CAD5807C085058F2015469CC12F17800A3E03C48078AAC7B18B1C2E6E28583003011C441515E93975E1234B2202A45899AB51885B0E5C2E4A5A5060001D464C0D6C3129C11214013C0C00302B2422AD23AA144D300B6081C85DEB02DC30FBE2D52E05AB84F1DDE5481791B98D193762C1A8C162C9A42263AEA5F99101C9821A61DADC2A10003B
而在本地磁碟中,檔案的二進位表示形式為: