將圖片插入到BLOB類型的字段中
專注于為中小企業(yè)提供網(wǎng)站制作、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)虎丘免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了上千企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
建立一個表:create table a(a blob);
建立一個目錄:create directory tmp as 'e:\';
建立一個PL/SQL塊:
declare
b_file bfile;
b_lob blob;
begin
insert into a(a) values(empty_blob()) return a into b_lob;
--為了使PL/SQL編譯成功,必須先為該列插入一個empty_blob() 值,return a into b_lob將該列與一個blog類型的變量綁定在一起,以后只要為b_lob賦值,即等于將該值插入了表中。
b_file:=bfilename('tmp','filename.jpg');
--tmp是建立的文件所在的目錄,filename.jpg是文件名;將文件轉(zhuǎn)換為bfile類型
dbms_lob.open(b_file,dbms_lob.file_readonly);--將b_file 以只讀的方式打開
dbms_lob.loadfromfile(b_lob,b_file,dbms_lob.getlength(b_file));-- 將b_file中的內(nèi)容轉(zhuǎn)換到b_lob中
dbms_lob.close(b_file);
commit;
end;
插入圖片/文本(blob /clob)到oracle數(shù)據(jù)庫(引用)
我們在寫OA的時候經(jīng)常遇到的問題就是員工圖片檔案的儲存問題,解決這個問題有兩個方法,
1.JSP/html頁面里面讀取web服務(wù)器上的圖片,也就是把圖片放到(上傳)到web 服務(wù)器上,然后用html 語句讀取:
img src=" 絕對或相對路徑 " border="0" /
2.就是上傳到數(shù)據(jù)庫里面(oracle).關(guān)于oracle 數(shù)據(jù)庫,它支持blob, 和clob, 分別對應(yīng)著圖片和文本(長字符串)操作
由于性能原因,我們還是要采用第二種方法,而且存到數(shù)據(jù)庫里面比較容易管理,是吧?
首先,我們要解決上傳問題,這里采用普遍使用的apache commons 組件里面的FileUpload class.
具體步驟如:
DiskFileUpload dfu=new DiskFileUpload();
dfu.setSizeMax(100000000);
dfu.setSizeThreshold(100000);
dfu.setRepositoryPath("f:\\public");
try{
List fileItems=dfu.parseRequest(request);
Iterator i=fileItems.iterator();
while(i.hasNext()){
FileItem fi=(FileItem)i.next();
if(!fi.isFormField()){
name=fi.getName();
size=fi.getSize();
if((name==null||name.equals(""))size==0)
continue;
}
name=fi.getName();
size=fi.getSize();
(InputStream)is=fi.getInputStream();
}
上面的代碼是web服務(wù)器接受上傳的代碼,參考文件已經(jīng)在我上篇寫的上傳文本文件里給出,今天,終于想明白了:
dfu.setRepositoryPath("f:\\public"); 的意思
原來是轉(zhuǎn)義字符也就是說\n\t等而要打印反斜杠要用\\,其實這個問題原先已經(jīng)知道,可是由于經(jīng)驗沒有寫過圖片上傳處理什么的,覺得很高深,也很可怕,哈哈,心里有點畏懼.看來基礎(chǔ)的東西,那怕一點點小細(xì)節(jié)也很重要,接著還有下面的java IO 問題.剛才讀core java 的時候突然發(fā)現(xiàn)在講io的時候特意提醒了這個問題,可是我沒有注意!
通過上面的代碼已經(jīng)實現(xiàn)文件上傳了.然后,我們要實現(xiàn)JDBC數(shù)據(jù)源鏈接,目的是要把數(shù)據(jù)插入到oracle.
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("jdbc/asdbCoreDS");
conn=ds.getConnection();
conn.setAutoCommit(false);
關(guān)于要import java.sql.* javax.sql.* java.naming.* 不再詳細(xì)敘述了
接著根據(jù)很有用的一篇文章的提示,插入blob類型一定要先1.插入一個空的
String insert=" insert into uploadpicture "+
" values(?, empty_blob()) " ;
2.然后找到這個blob的oracle 里面的游標(biāo):
String findCursor=" select content "+
" from uploadpicture "+
" where name=? for update ";
注意這個for update(注意?。?!必須加for update,這將鎖定該行,直至該行被修改完畢,保證不產(chǎn)生并發(fā)沖突。這里還是難以理解,先記下來吧)
3.然后再修改
String update=" update uploadpicture "+
" set content=? "+
" where name=? ";
這里的問號是為PreparedStatement參數(shù)處理而寫的!
寫這個程序用到了oracle.sql.BLOB class ,這個類是用來操作BLOB數(shù)據(jù)類型的
當(dāng)我們通過ResultSet 對象得到
blob=(BLOB)rs.getBlob(1);
的時候我不知道如何處理了,Blob 是什么?String, int ,long? 我現(xiàn)在也不明白!估計CSDN上的人也不明白,否則我發(fā)個帖子半天沒有人回答,也許是很爛,也許是太簡單了,大家不屑一顧,看來我還要繼續(xù)追趕!
不發(fā)牢騷了,回到程序里(總覺得自己的發(fā)散思維很強(qiáng),看來寫程序的時候不能這樣,多虧java 是純面向?qū)ο笳Z言,如果是過程就麻煩了)
我們?nèi)绾翁幚磉@個blob 呢?回答是,不管它是什么,直接寫入 BufferedOutputStream out1 =new BufferedOutputStream(blob.getBinaryOutputStream());
這里是建立了緩沖寫如blob 的流(注意getBinaryOutputStream()已經(jīng)不被贊成使用了,一定有更優(yōu)秀的方法替代!),說到流,我到現(xiàn)在還有點暈,類很多,不知道究竟用哪個好!
基礎(chǔ)的東西非常重要,這曾經(jīng)是我的口頭禪,這里用到了流的讀入寫和寫入,有些流是從文件或其它位置上讀取字節(jié)(如, FileInputStream),有寫流是把字節(jié)組合成有用的數(shù)據(jù)(如, DataInputStream).我們讀取數(shù)字的時候,需要首先建議一個FileInpuStream, 然后, 再把該類的對象傳遞給DataInputStream
FileInputStream fin=new FileInputStream(“emp.dat”);
DataInputStream din=new DataInputStream(fin);//把fin傳遞給din
double s=din.readDouble();
默認(rèn)情況下,流是沒有緩沖的, 如果使用緩沖就是
DataInputStream din=new DataInputStream(
new BufferedInputStream(new FileINputStream(“emp.dat”)));
有了這點理解也很管用,
BufferedOutputStream out1 =new BufferedOutputStream(blob.getBinaryOutputStream());
就是建立一個緩沖寫的對象到blob.注意這里的out1 不是out,否則程序運行的時候不能打印了temp 數(shù)據(jù)了!
已經(jīng)準(zhǔn)備好如何寫了, 可是如何讀呢?
BufferedInputStream in=new BufferedInputStream(is);
在我們上傳的時候 (InputStream)is=fi.getInputStream();
讀取圖片為輸入的流.保存為is 對象,然后就用到這里了,準(zhǔn)備好了讀和寫了,我們開始干活:
int c;
while((c=in.read())!=-1) {out1.write(c);}
in.close();
out1.close();
通過緩沖一個個讀數(shù)據(jù),然后一個個寫數(shù)據(jù).-1 為文件的末尾,
最后當(dāng)讀寫完成后我們要關(guān)閉讀寫對象!
程序分析就是這樣,以后還要對此問題進(jìn)行研究,最后還要注意,
%@ page contentType="image/jpeg;charset=GBK"%
不是
%@ page contentType="text/html;charset=GBK"%
否則是以文字顯示圖片---亂碼.
這里研究了上傳圖片到oralce 里面的程序,關(guān)于顯示還要麻煩一點,借助資料我實現(xiàn)了,明天再研究一下.
//插入上傳圖片到數(shù)據(jù)庫
%@ page contentType="text/html;charset=GBK"%
%@ page import="java.util.*"%
%@ page import="java.io.*"%
%@ page import="org.apache.commons.*"%
%@ page import="org.apache.commons.fileupload.*"%
%@ page import="java.sql.*"%
%@ page import="javax.sql.*"%
%@ page import="javax.naming.*"%
%@ page import="oracle.sql.*"%
html
head
meta http-equiv="Content-Type" content="text/html; charset=GBK"
titlegetPicture.jsp/title
/head
body
%
request.setCharacterEncoding("GBK");
String name=null;
long size=0;
Connection conn=null;
String insert=" insert into uploadpicture "+
" values(?, empty_blob()) " ;
String findCursor=" select content "+
" from uploadpicture "+
" where name=? for update ";
String update=" update uploadpicture "+
" set content=? "+
" where name=? ";
BLOB blob=null;
InputStream is=null;
DiskFileUpload dfu=new DiskFileUpload();
dfu.setSizeMax(100000000);
dfu.setSizeThreshold(100000);
dfu.setRepositoryPath("f:\\public");
try{
List fileItems=dfu.parseRequest(request);
Iterator i=fileItems.iterator();
while(i.hasNext()){
FileItem fi=(FileItem)i.next();
if(!fi.isFormField()){
name=fi.getName();
size=fi.getSize();
if((name==null||name.equals(""))size==0)
continue;
}
name=fi.getName();
size=fi.getSize();
is=fi.getInputStream();
}
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("jdbc/asdbCoreDS");
conn=ds.getConnection();
conn.setAutoCommit(false);
//step 1
PreparedStatement ps=conn.prepareStatement(insert);
ps.setString(1, name);
int a=ps.executeUpdate();
if(a0)
out.println("insert success!"+"br");
//step 2
ps=conn.prepareStatement(findCursor);
ps.setString(1, name);
ResultSet rs=ps.executeQuery();
while(rs.next())
{
blob=(BLOB)rs.getBlob(1);
out.println("find cursor success!"+"br");
out.println("cursor :"+blob+"br");
//step 3
ps=conn.prepareStatement(update);
ps.setBlob(1, blob);
ps.setString(2, name);
ps.executeUpdate();
ps.close();
BufferedOutputStream out1 =new BufferedOutputStream(blob.getBinaryOutputStream());
BufferedInputStream in=new BufferedInputStream(is);
int c;
while((c=in.read())!=-1) {out1.write(c);}
in.close();
out1.close();
out.println("update success!"+"br");}
conn.commit();
}
catch(SQLException se)
{se.printStackTrace();}
catch(FileUploadException fue)
{fue.printStackTrace();}
%
/body
/html
//顯示數(shù)據(jù)庫里面的圖片
%@ page contentType="image/jpeg;charset=GBK"%
%@ page import="java.sql.*"%
%@ page import="javax.sql.*"%
%@ page import="javax.naming.*"%
%@ page import="java.io.*"%
%@ page import="com.sun.image.codec.jpeg.*"%
%@ page import="javax.imageio.*"%
%@ page import="java.util.*"%
%@ page import="java.awt.image.*"%
html
head
meta http-equiv="Content-Type" content="image/jpeg; charset=GBK"
titleshowDBImage.jsp/title
/head
body
%
String showImage=" select * "+
" from uploadpicture "+
" where name=′TXC with snow.JPG′ " ;
Connection conn=null;
BufferedInputStream inputImage=null;
try{
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("jdbc/asdbCoreDS");
conn=ds.getConnection();
Statement st=conn.createStatement();
ResultSet rs=st.executeQuery(showImage);
while(rs.next())
{
oracle.sql.BLOB blob=(oracle.sql.BLOB)rs.getBlob("content");
inputImage =new BufferedInputStream(blob.getBinaryStream());
/*String name=rs.getString(1);
String content=rs.getString(2);
out.println(name+"br");*/}
BufferedImage image=null;
image=ImageIO.read(inputImage);
ServletOutputStream sos=response.getOutputStream();
JPEGImageEncoder encoder=JPEGCodec.createJPEGEncoder(sos);
encoder.encode(image);
inputImage.close();
conn.commit();
}
catch(SQLException se)
{se.printStackTrace();
conn.rollback(); }
catch(IOException ie)
{ie.printStackTrace();}
%
/body
/html
我給你個例子你就知道了。。表和列名改成你相應(yīng)的列和表就可以了。不明白的繼續(xù)問我吧。
declare
src_lob?blob;
file_lob?bfile;
amount?int;
src_offset?int:=1;
file_offset?int:=1;
filename_in?varchar2(20):='filename_in';--為你要插入的文件名稱
id_in?number(6):=id;
begin
file_lob:=bfilename('UTLLOBDIR',filename_in);--UTLLOBDIR為你所建立的目錄名稱
select?photo?into?src_lob?from?lob_employee?where?id=id_in?for?update;
if?dbms_lob.fileexists(file_lob)=1?then
dbms_output.put_line('文件名為:'||filename_in||'的圖片存在,正在進(jìn)行圖片寫入');
dbms_lob.fileopen(file_lob,0);--打開你要插入的文件
amount:=dbms_lob.getlength(file_lob);
dbms_lob.loadblobfromfile(src_lob,file_lob,amount,src_offset,file_offset);
dbms_output.put_line('文件名為:'||filename_in||'的圖片寫入完畢!');
dbms_lob.close(file_lob);
else
raise_application_error(-20001,'文件名為:'||filename_in||'的圖片不存在,請檢查!');
dbms_output.put_line('文件名為:'||filename_in||'的圖片不存在,請檢查!');
end?if;
exception
when?no_data_found?then
raise_application_error(-20002,'個人編碼為:'||id_in||'的個人信息不存在,請檢查!');
when?others?then
dbms_output.put_line('錯誤編碼:'||SQLCODE);
dbms_output.put_line('錯誤信息:'||SQLERRM);
end;
create table test
(
NID VARCHAR2(1) not null,
IMG BLOB,
zhengqueFlag VARCHAR2(1),
cuowuFlag VARCHAR2(1)
)
說明:
1、IMG字段只需要保存圖片,將圖片信息經(jīng)過Base64編碼,存到數(shù)據(jù)庫BLOB字段中。顯示的時候要經(jīng)過Base64解碼。
2、對于像“正確”、“錯誤”用標(biāo)志位在區(qū)別。你可以用1表示正確、0表示錯誤。當(dāng)然你也可以用漢字的保存這樣的信息。自己來設(shè)計。
然后你到網(wǎng)上查一下怎么樣對BLOB字段進(jìn)行操作。如果不行,我在增加回復(fù)。
我只說說思路吧,代碼你自己寫哈!
首先我建議使用SmartUpload這個jar包,至于怎么使用,可以百度
點擊上傳的時候,后臺要處理的步驟是:
a.根據(jù)“電影類型”判斷當(dāng)前路徑是否已經(jīng)存在系統(tǒng)所在物理環(huán)境的指定位置,如果不存在創(chuàng)建該路徑文件夾
b.如果存在,將該文件存在指定位置.
然后將該路徑保存到oracle中