在開發(fā)過程中,經(jīng)常會遇到oracle中存圖片的情況,下面就為您想介紹一個可以輕松在oracle中存圖片的方法,希望對您能有所幫助。
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了馬山免費建站歡迎大家使用!
一個存儲圖片文件的過程,任何開發(fā)工具都可以通過調(diào)用過程把圖片文存儲到數(shù)據(jù)庫中。
oracle中存圖片的詳細步驟:
SQL connect chanet/chanet@oradb;
已連接。
SQL CREATE TABLE IMAGE_LOB (T_ID VARCHAR2 (5) NOT NULL,T_IMAGE BLOB NOT NULL);
表已創(chuàng)建。
SQL CREATE OR REPLACE DIRECTORY IMAGES AS 'C:\Oracle'; --圖片目錄
目錄已創(chuàng)建。
SQL CREATE OR REPLACE PROCEDURE IMG_INSERT (TID VARCHAR2,FILENAME VARCHAR2) AS F_LOB BFILE; B_LOB BLOB; BEGIN INSERT INTO IMAGE_LOB (T_ID, T_IMAGE) VALUES (TID,EMPTY_BLOB ()) RETURN T_IMAGE INTO B_LOB; F_LOB:= BFILENAME ('IMAGES', FILENAME); DBMS_LOB.FILEOPEN (F_LOB, DBMS_LOB.FILE_READONLY); DBMS_LOB.LOADFROMFILE (B_LOB, F_LOB, DBMS_LOB.GETLENGTH (F_LOB)); DBMS_LOB.FILECLOSE (F_LOB); COMMIT; END; /
過程已創(chuàng)建。
SQL EXEC IMG_INSERT('1','f_TEST.jpg');
PL/SQL 過程已成功完成。
整個流程分為四步,連接oracle數(shù)據(jù)庫 - 讀取blob圖片字段 - 對圖片進行縮放 -把圖片展示在jsp頁面上。
下面進行詳細描述:
1. java連接Oracle
注:數(shù)據(jù)庫是Oracle10g版本為10.2.0, 在數(shù)據(jù)庫中,圖片字段類型為BLOB。
java中通常使用的是通過jdbc驅(qū)動來連接數(shù)據(jù)庫,oracle也不例外,因此必須下載一個Oracle驅(qū)動的jdbc需要去網(wǎng)上進行下載,名稱為 ojdbc14.jar。
下載地址為:
下載了驅(qū)動之后,可以使用驅(qū)動里提供的接口進行連接,具體代碼如下:
import java.sql.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.AffineTransformOp;
import java.awt.geom.AffineTransform;
public class OracleQueryBean {
private final String oracleDriverName = "oracle.jdbc.driver.OracleDriver";
private Connection myConnection = null;
/*圖片表名*/
private String strTabName;
/*圖片ID字段名*/
private String strIDName;
/*圖片字段名*/
private String strImgName;
/**
* 加載java連接Oracle的jdbc驅(qū)動
*/
public OracleQueryBean(){
try{
Class.forName(oracleDriverName);
}catch(ClassNotFoundException ex){
System.out.println("加載jdbc驅(qū)動失敗,原因:" + ex.getMessage());
}
}
/**
* 獲取Oracle連接對象
* @return Connection
*/
public Connection getConnection(){
try{
//用戶名+密碼; 以下使用的Test就是Oracle里的表空間
//從配置文件中讀取數(shù)據(jù)庫信息
GetPara oGetPara = new GetPara();
String strIP = oGetPara.getPara("serverip");
String strPort = oGetPara.getPara("port");
String strDBName = oGetPara.getPara("dbname");
String strUser = oGetPara.getPara("user");
String strPassword = oGetPara.getPara("password");
this.strTabName = oGetPara.getPara("tablename");
this.strIDName = oGetPara.getPara("imgidname");
this.strImgName = oGetPara.getPara("imgname");
String oracleUrlToConnect ="jdbc:oracle:thin:@"+strIP+":"+strPort+":"+strDBName;
this.myConnection = DriverManager.getConnection(oracleUrlToConnect, strUser, strPassword);
}catch(Exception ex){
System.out.println("Can not get connection:" + ex.getMessage());
System.out.println("請檢測配置文件中的數(shù)據(jù)庫信息是否正確." );
}
return this.myConnection;
}
}
2. 讀取blob字段
在OracleQueryBean類中增加一個函數(shù),來進行讀取,具體代碼如下:
/**
* 根據(jù)圖片在數(shù)據(jù)庫中的ID進行讀取
* @param strID圖片字段ID
* @param w 需要縮到的寬度
* @param h 需要縮到高度
* @return
*/
public byte[] GetImgByteById(String strID, int w, int h){
//System.out.println("Get img data which id is " + nID);
if(myConnection == null)
this.getConnection();
byte[] data = null;
try {
Statement stmt = myConnection.createStatement();
ResultSet myResultSet = stmt.executeQuery("select " + this.strIDName + " from " + this.strTabName + " where " + this.strIDName + "=" + strID);
StringBuffer myStringBuffer = new StringBuffer();
if (myResultSet.next()) {
java.sql.Blob blob = myResultSet.getBlob(this.strImgName);
InputStream inStream = blob.getBinaryStream();
try {
long nLen = blob.length();
int nSize = (int) nLen;
//System.out.println("img data size is :" + nSize);
data = new byte[nSize];
inStream.read(data);
inStream.close();
} catch (IOException e) {
System.out.println("獲取圖片數(shù)據(jù)失敗,原因:" + e.getMessage());
}
data = ChangeImgSize(data, w, h);
}
System.out.println(myStringBuffer.toString());
myConnection.commit();
myConnection.close();
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
return data;
}
3. 縮放圖片
因為圖片的大小可能不一致,但是在頁面中輸出的大小需要統(tǒng)一,所以需要
在OracleQueryBean類中增加一個函數(shù),來進行縮放,具體代碼如下:
/**
* 縮小或放大圖片
* @param data 圖片的byte數(shù)據(jù)
* @param w 需要縮到的寬度
* @param h 需要縮到高度
* @return 縮放后的圖片的byte數(shù)據(jù)
*/
private byte[] ChangeImgSize(byte[] data, int nw, int nh){
byte[] newdata = null;
try{
BufferedImage bis = ImageIO.read(new ByteArrayInputStream(data));
int w = bis.getWidth();
int h = bis.getHeight();
double sx = (double) nw / w;
double sy = (double) nh / h;
AffineTransform transform = new AffineTransform();
transform.setToScale(sx, sy);
AffineTransformOp ato = new AffineTransformOp(transform, null);
//原始顏色
BufferedImage bid = new BufferedImage(nw, nh, BufferedImage.TYPE_3BYTE_BGR);
ato.filter(bis, bid);
//轉(zhuǎn)換成byte字節(jié)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bid, "jpeg", baos);
newdata = baos.toByteArray();
}catch(IOException e){
e.printStackTrace();
}
return newdata;
}
4. 展示在頁面
頁面使用OracleQueryBean來根據(jù)用戶提供的圖片id進行查詢,在讀取并進行縮放后,通過jsp頁面進行展示,具體代碼如下:
%@ page language="java" contentType="text/html;;charset=gbk" %
jsp:useBean id="OrcleQuery" scope="page" class="HLFtiDemo.OracleQueryBean" /
%
response.setContentType("image/jpeg");
//圖片在數(shù)據(jù)庫中的 ID
String strID = request.getParameter("id");
//要縮略或放大圖片的寬度
String strWidth = request.getParameter("w");
//要縮略或放大圖片的高度
String strHeight = request.getParameter("h");
byte[] data = null;
if(strID != null){
int nWith = Integer.parseInt(strWidth);
int nHeight = Integer.parseInt(strHeight);
//獲取圖片的byte數(shù)據(jù)
data = OrcleQuery.GetImgByteById(strID, nWith, nHeight);
ServletOutputStream op = response.getOutputStream();
op.write(data, 0, data.length);
op.close();
op = null;
response.flushBuffer();
//清除輸出流,防止釋放時被捕獲異常
out.clear();
out = pageContext.pushBody();
}
%
5. OracleQueryBean查詢類的整體代碼
OracleQueryBean.java文件代碼如下所示:
import java.sql.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.AffineTransformOp;
import java.awt.geom.AffineTransform;
public class OracleQueryBean {
private final String oracleDriverName = "oracle.jdbc.driver.OracleDriver";
private Connection myConnection = null;
/*圖片表名*/
private String strTabName;
/*圖片ID字段名*/
private String strIDName;
/*圖片字段名*/
private String strImgName;
/**
* 加載java連接Oracle的jdbc驅(qū)動
*/
public OracleQueryBean(){
try{
Class.forName(oracleDriverName);
}catch(ClassNotFoundException ex){
System.out.println("加載jdbc驅(qū)動失敗,原因:" + ex.getMessage());
}
}
/**
* 獲取Oracle連接對象
* @return Connection
*/
public Connection getConnection(){
try{
//用戶名+密碼; 以下使用的Test就是Oracle里的表空間
//從配置文件中讀取數(shù)據(jù)庫信息
GetPara oGetPara = new GetPara();
這文章確實寫的不錯,你可以看原文
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字段進行操作。如果不行,我在增加回復(fù)。
商品圖片,用戶上傳的頭像,其他方面的圖片。目前業(yè)界存儲圖片有兩種做法:
1、 把圖片直接以二進制形式存儲在數(shù)據(jù)庫中
一般數(shù)據(jù)庫提供一個二進制字段來存儲二進制數(shù)據(jù)。比如MySQL中有個blob字段。Oracle數(shù)據(jù)庫中是blob或bfile類型
2、 圖片存儲在磁盤上,數(shù)據(jù)庫字段中保存的是圖片的路徑。
一、圖片以二進制形式直接存儲在數(shù)據(jù)庫中
第一種存儲實現(xiàn)(PHP語言):
大體思路:
1、將讀取到的圖片用php程序轉(zhuǎn)化成二進制形式。再結(jié)合insert into 語句插入數(shù)據(jù)表中的blob類型字段中去。
3、 從數(shù)據(jù)庫取出圖片展示的時候。則是直接發(fā)送圖片內(nèi)容
4、
$row=mysql_fetch_object($result);
Header( "Content-type: image/gif");
echo $row-this_image;
實現(xiàn)代碼如下:
$PicturePath = ‘/tmp/xxxjgjgj.jpg’;//假設(shè)這是上傳的圖片,php放在一個臨時文件夾。腳本執(zhí)行完畢后自動刪除了。
$imgStream = fread(fopen($PicturePath, "r");
$blob_img = fread(fopen($imgStream, "r"), filesize($PicturePath));
$sql =” INSERT INTO Images (this_image) VALUES ($blob_img)";
注:this_image就是數(shù)據(jù)表中一個blob字段類型的字段
================取出展示圖片代碼
$result=mysql_query("SELECT * FROM Images WHERE PicNum=$PicNum") or die("Cant perform Query");
$row=mysql_fetch_object($result);
Header( "Content-type: image/gif");
echo $row- this_image;
總結(jié):處理代碼感覺還真比較麻煩。其實,我從來沒用過在數(shù)據(jù)庫中以二進制存儲圖片的做法。我們用得更多的是存儲圖片的路徑,實際圖片是在磁盤上保存的(圖片二進制放到數(shù)據(jù)庫,把數(shù)據(jù)庫的負擔(dān)弄重了)。
據(jù)我了解,互聯(lián)網(wǎng)環(huán)境中,大訪問量,數(shù)據(jù)庫速度和性能方面很重要。一般在數(shù)據(jù)庫存儲圖片的做法比較少,更多的是將圖片路徑存儲在數(shù)據(jù)庫中,展示圖片的時候只需要連接磁盤路徑把圖片載入進來即可。因為圖片是屬于大字段。一張圖片可能1m到幾m。
有個原則:圖片盡量不要存儲在數(shù)據(jù)庫中(是指不要二進制形式保存到字段,而只保存圖片的路徑)。這樣的大字段數(shù)據(jù)會加重數(shù)據(jù)庫的負擔(dān),拖慢數(shù)據(jù)庫。在大并發(fā)訪問的情況下很重要。這是一個經(jīng)驗。去看看dba對數(shù)據(jù)庫性能調(diào)優(yōu)方面的分析都能得到這個答案的:就是圖片不要存儲在數(shù)據(jù)庫中。
就像這個規(guī)則一樣:文章分為標(biāo)題、作者、添加時間、更新時間、文章內(nèi)容、文章關(guān)鍵字
文章內(nèi)容一般是比較長的。經(jīng)常使用text字段去存儲。文章的內(nèi)容就屬于大字段。一般文章內(nèi)容可以拆分到單獨一個表中去。不要與文章信息存儲在一張表里面。
我理解的原理是:mysql中一張表的數(shù)據(jù)是全部在一個數(shù)據(jù)文件中的。如果大字段的數(shù)據(jù)也存儲在里面。程序展示列表,比如文章列表。這個時候根本不需要展示文章內(nèi)容的。但是仍然會影響速度,數(shù)據(jù)庫查找數(shù)據(jù)其實就是掃描那個數(shù)據(jù)文件,文件容量越小,速度就會越快(為什么單表的容量在1g-2g的時候基本上要分表了)。拆分出去到一張單獨的表,就是單獨的文件了。我覺得,舉一反三,相互獨立,分離的思想不僅在系統(tǒng)開發(fā)中用到,在現(xiàn)實生活中經(jīng)常存在的。相互混合,就會造成相互影響。小巧,簡潔是一種思想。
可以看看這篇翻譯的文章,
http//developer.51cto.com/art/201211/364472.htm
作者建議,三種東西永遠不要放到數(shù)據(jù)庫里,圖片,文件,二進制數(shù)據(jù)。作者的理由是,
對數(shù)據(jù)庫的讀/寫的速度永遠都趕不上文件系統(tǒng)處理的速度
數(shù)據(jù)庫備份變的巨大,越來越耗時間
對文件的訪問需要穿越你的應(yīng)用層和數(shù)據(jù)庫層
把圖片縮略圖存到數(shù)據(jù)庫里?很好,那你就不能使用nginx或其它類型的輕量級服務(wù)器來處理它們了。
給自己行個方便吧,在數(shù)據(jù)庫里只簡單的存放一個磁盤上你的文件的相對路徑,或者使用S3(備注:亞馬遜云服務(wù))或CDN之類的服務(wù)。
============================================================
關(guān)于mysql中的blob類型
bolb像int型那樣,分為blob、MEDIUMBLOB、LONGBLOB。其實就是從小到大,
blob 容量為64KB ,MEDIUMBLOB 容量為16M,LONGBLOB 容量為4G。
說實話,圖片用這樣子存儲用得還真少。使用php函數(shù)serialize進行序列化的值,我看到有人存入這個字段中去。
php手冊:serialize返回字符串,此字符串包含了表示 value 的字節(jié)流,可以存儲于任何地方。
mysql中blob字段存儲圖片有個通信大小的設(shè)置:
圖片要傳輸給mysql存儲起來,那么需要涉及到數(shù)據(jù)通信。mysql中有個配置是限制通信數(shù)據(jù)大小的。
my.conf配置文件中的max_allowed_packet,mysql默認的值是1M。
好多圖片尤其是原始圖可能不止1m。傳輸?shù)臄?shù)據(jù)(也就是圖片)超過這個設(shè)置大小。結(jié)果就會出錯
呵呵,限制挺多。感覺好麻煩。這樣子明顯占用與mysql交互的通信時間嘛。延長響應(yīng)時長了。我直接丟個圖片路徑”images/xxxx”給mysql。沒這么耗費資源。
其實所謂的性能,最關(guān)鍵是數(shù)據(jù)庫性能。因為隨著數(shù)據(jù)庫數(shù)據(jù)量增大,大部分時間耗費是在php,Java等語言等待數(shù)據(jù)庫返回數(shù)據(jù)的過程中耗費時間。
網(wǎng)站訪問量大了后,具體的語言不是瓶頸,瓶頸都在數(shù)據(jù)庫。用c,,php,java,net都能操作mysql數(shù)據(jù)庫獲取數(shù)據(jù)。語言之間可能存在速度執(zhí)行差異,但是其實這種差別已經(jīng)很小了。至少我覺得,給予用戶感覺不到明顯。執(zhí)行相差0.0001秒用戶感覺并沒有明顯的區(qū)別。可能說,大并發(fā)(很多用戶同時訪問)的時候,就會體現(xiàn)到差別了。其實我覺得,大并發(fā)訪問是數(shù)據(jù)庫瓶頸。等待數(shù)據(jù)庫給予數(shù)據(jù)。沒達到一定級別實在體現(xiàn)不了差別。數(shù)據(jù)庫數(shù)據(jù)量達到一定級別。語言相差0.001s會給予用戶體驗上的差別。我想,這也是為什么php很適合做web開發(fā)了。解析頁面速度快(解釋型語言,不需要編譯)。可以用java來與數(shù)據(jù)庫打交道獲取數(shù)據(jù)。php不直接操作數(shù)據(jù)庫,而是調(diào)用java提供的數(shù)據(jù)接口,獲取數(shù)據(jù),馬上展示在頁面中。這是利用了php的頁面執(zhí)行速度快的一個優(yōu)勢。
備份圖片數(shù)據(jù)和遷移數(shù)據(jù)方便
圖片以二進制形式存儲在數(shù)據(jù)庫,有一個好處:備份的時候方便。直接備份數(shù)據(jù)庫,圖片也跟著備份。換句話說,遷移環(huán)境的時候是方便。
而圖片放在磁盤上的話,數(shù)據(jù)庫中存儲的只是圖片路徑。備份數(shù)據(jù)庫后。磁盤上的圖片也要跟著備份才行。
不過我覺得,備份這個好處不是很明顯。圖片在磁盤上,備份磁盤也沒很大的事情。打包壓縮也可以了。互聯(lián)網(wǎng)環(huán)境畢竟與傳統(tǒng)的軟件開發(fā)不同,web開發(fā)比較關(guān)注網(wǎng)站速度。也就是數(shù)據(jù)庫的速度。就像互聯(lián)網(wǎng)開發(fā)中,有時候為了速度,用空間換時間的做法比較普遍,所以往往在設(shè)計數(shù)據(jù)庫的時候并不一定遵循傳統(tǒng)數(shù)據(jù)庫設(shè)計三大范式。
數(shù)據(jù)庫中保存的是圖片路徑的話,在web開發(fā)環(huán)境下,其實有個更好處,就是cdn加速。就是下面要進行總結(jié)的地方。
二、數(shù)據(jù)庫中保存圖片路徑
一般是這樣子的:
按照年月日生成路徑。具體是按照年月日還是按照年月去生成路徑,根據(jù)自己需要(不一定是按照日期去生成)。
理解為什么要分散到多個文件夾中去才是關(guān)鍵,涉及到一個原理就明白了:
操作系統(tǒng)對單個目錄的文件數(shù)量是有限制的。當(dāng)文件數(shù)量很多的時候。從目錄中獲取文件的速度就會越來越慢。所以為了保持速度,才要按照固定規(guī)則去分散到多個目錄中去。
圖片分散到磁盤路徑中去。數(shù)據(jù)庫字段中保存的是類似于這樣子的”images/2012/09/25/ 1343287394783.jpg”
原來上傳的圖片文件名稱會重新命名保存,比如按照時間戳來生成,1343287394783. jpg。這樣子是為了避免文件名重復(fù),多個人往同一個目錄上傳圖片的時候會出現(xiàn)。
反正用什么樣的規(guī)則命名圖片,只要做到圖片名稱的唯一性即可。
比如網(wǎng)站的并發(fā)訪問量大,目錄的生成分得月細越好。比如精確到小時,一個小時都可以是一個文件夾。同時0.001秒有兩個用戶同時在上傳圖片(因為那么就會往同一個小時文件夾里面存圖片)。因為時間戳是精確到秒的。為了做到圖片名稱唯一性而不至于覆蓋,生成可以在在時間戳后面繼續(xù)加毫秒微秒等。總結(jié)的規(guī)律是,并發(fā)訪問量越大。就越精確就好了。
我現(xiàn)在還沒碰到需要這么精細的。概率比較少。
有個方面總結(jié)一下:為什么保存的磁盤路徑,是”images/2012/09/25/1343287394783.jpg”,而不是” /images/2012/09/25/ 1343287394783.jpg”(最前面帶有斜杠)
我的理解:
連那個斜杠都不要。這里也是做到方便以后系統(tǒng)擴展。
在頁面中需要取出圖片路徑展示圖片的時候,如果是相對路徑,則可以使用”./”+”images/2012/09/25/1343287394783.jpg”進行組裝。
如果需要單獨的域名(比如做cdn加速的時候)域名,img1.xxx.com,img2.xxx.com這樣的域名,
直接組裝 “http//img1.xxx.com/”+”images/2012/09/25/1343287394783.jpg”
當(dāng)然數(shù)據(jù)庫是可以在前面加斜杠/保存起來,/images/2012/09/25/ 1343287394783.jpg
其實不方便統(tǒng)一。比如相對路徑載入圖片的時候,則是”.”+” /images/2012/09/25/ 1343287394783.jpg”
可能我還沒體會到壞處,以后會遇到問題的。不過,遵循慣例不加斜杠” images/2012/09/25/ 1343287394783.jpg”就對了。
涉及到一個新問題:為什么大部分系統(tǒng)都不會域名保存進去,像這樣子http//wwwxxx.com/images/2012/09/25/1343287394783.jpg保存到數(shù)據(jù)庫中
曾經(jīng)與一個上海的網(wǎng)友聊天,他也是習(xí)慣不會把域名保存數(shù)據(jù)庫中過去。但當(dāng)時我們兩聊的時候,他對”域名保存進去的做法”與”不保存域名進去”也沒有一個明確利弊。他就覺得,沒有什么明顯的區(qū)別啊。
了解的知識越多,越有利于我們做決定。可能就是一個”感覺區(qū)別不是很大”的影響下,去做一個決定,反而對后面是比較大的影響的。至少是增加自己的工作量了。
其實把域名保存進去,也不是什么滔天大罪的事情。但凡是經(jīng)驗豐富的開發(fā)人員都不會這樣子做。這是一個經(jīng)驗積累出來的,所以上海那個網(wǎng)友也對此并沒有明顯的概念很正常,他說他不知道cdn方面的(當(dāng)然覺得存?zhèn)€域名進去沒什么大不了的)。需要了解cdn知識,什么情況下會用到cdn知識。
雖然是做開發(fā)人員,不需要關(guān)注運維和服務(wù)器之類的知識。不過了解一些就有利于理解了。
這里涉及到cdn加速。
關(guān)于cdn原理(就是內(nèi)容分發(fā)網(wǎng)絡(luò))
cdn,我理解其本質(zhì)就是為了解決距離遠產(chǎn)生的速度問題,使用就近的服務(wù)。
從中國請求美國一臺服務(wù)器上的圖片。一般比較慢,因為距離這么遠,網(wǎng)絡(luò)傳輸是存在損耗的,距離越遠,傳輸?shù)臅r間就越長。一般會看到瀏覽器左下角顯示:“已響應(yīng),正在傳輸數(shù)據(jù)..”。這不是服務(wù)器本身問題了。實際上服務(wù)器早就響應(yīng)請求,把數(shù)據(jù)發(fā)給客戶端,但是網(wǎng)絡(luò)問題,就一直在傳輸,沒傳完了。
在中國,是南北距離遠的問題。南北還會涉及到跨網(wǎng),南方用戶使用電信居多,北方用戶網(wǎng)通居多。兩個線路需要跨越,會有時間延遲。北京到廣州的距離,如果直接請求
cdn加速就是適應(yīng)這個需求產(chǎn)生的:現(xiàn)在不請求美國的服務(wù)器。直接在中國安放節(jié)點(節(jié)點是比較籠統(tǒng)的詞語,可以理解成一臺服務(wù)器,也可以理解成一個機房,就是一個點嘛),請求距離近的節(jié)點。這樣子就不需要那么遠的距離了。
記得以前在長沙的網(wǎng)站,團購以城市分站的形式。北京和長沙用的是同一套程序。服務(wù)器在長沙。北京用戶訪問北京站的時候,實際上需要遠距離訪問長沙的服務(wù)器。速度怎么都快不起來。跟服務(wù)器性能完全沒關(guān)系。當(dāng)時不懂這些。不清楚怎么折騰。看那本《前端優(yōu)化技巧》,想辦法去做js代碼壓縮,瀏覽器緩存之類的。實際上瞎折騰。不是說這些前端優(yōu)化不重要,哲學(xué)上有主次矛盾之分,瓶頸在哪里就去突破哪里。沒解決主要矛盾,問題并不會迎刃而解。當(dāng)時也不是數(shù)據(jù)庫瓶頸。如果去優(yōu)化數(shù)據(jù)庫。也不會明顯改善。就那點數(shù)據(jù)量。根本就達不到瓶頸。哪里談得上主要矛盾。隨著后來去其他公司工作,接觸一些東西,類似不找瓶頸的優(yōu)化例子發(fā)生在身邊好幾次了,先沒找到瓶頸就瞎去優(yōu)化。我的同事可能是抱著多多益善的心態(tài)去做的,但主要矛盾(技術(shù)上說是瓶頸)沒找到,也沒改善。
當(dāng)時如果沒想到是距離問題。也就不會想到cdn,當(dāng)時其實我根本不知道cdn服務(wù)。我只知道,google這些網(wǎng)站肯定在中國部署的服務(wù)器,要不然,中國用戶還去訪問美國的服務(wù)器,那再好的服務(wù)器都會速度慢的。
由于自己搭建cdn環(huán)境和機房的資金比較大(需要大量的服務(wù)器),也需要人力維護。反正一般的公司弄不起,其實根本不劃算。淘寶以前用商用的cdn服務(wù),后來商用的扛不住了,就搭建了自己的cdn網(wǎng)。我不知道新浪有沒有自己搭建,但其實我覺得跟淘寶的特點有關(guān),店鋪很多,無論是商品還是交易記錄總計起來商品很多的圖片,圖片都是靜態(tài)的部分,cdn本來就是用來做靜態(tài)的(圖片,css,js等)請求分發(fā)用的。
我之前在網(wǎng)上看到一句話,cdn網(wǎng)絡(luò)不是一般的公司玩得起的。
一般的公司自己搭建cdn網(wǎng)絡(luò)成本高,所以就有商業(yè)的cdn提供付費租用服務(wù),這是一項很成熟的業(yè)務(wù),很多這樣的公司,大部分全國性的互聯(lián)網(wǎng)公司都會使用到cdn。
總結(jié):cdn服務(wù)。對于靜態(tài)內(nèi)容是非常適合的。所以像商品圖片,隨著訪問量大了后,租用cdn服務(wù),只需要把圖片上傳到他們的服務(wù)器上去。
例子:北京訪問長沙服務(wù)器,距離太遠。我完全可以把商品圖片,放到北京的云服務(wù)(我覺得現(xiàn)在提供給網(wǎng)站使用的云存儲其實就是cdn,給網(wǎng)站提供分流和就近訪問)上去。這樣子北京用戶訪問的時候,實際上圖片就是就近獲取。不需要很長距離的傳輸。
自己用一個域名img.xxxcom來載入圖片。這個域名解析到北京的云服務(wù)上去。
做法:數(shù)據(jù)庫中保存的是” images/2012/09/25/1343287394783.jpg”,
這些圖片實際上不存儲在web服務(wù)器上。上傳到北京的cdn服務(wù)器上去。
我從數(shù)據(jù)庫取出來,直接”img.xxxcom/”+” images/2012/09/25/1343287394783.jpg”
比如如果還有多個,就命名img1.xxcom、img2.xxcom
反正可以隨便。所以如果把域名直接保存進去。就顯得很麻煩了。遷移麻煩。
像淘寶,凡客,亞馬遜這些電子商務(wù)網(wǎng)站,我們看到請求的時候,下面往往會有
img1.xxx.cdncom
img2.xxx.cdncom
其實他們保存在數(shù)據(jù)庫中的是相對路徑。有些是不需要在數(shù)據(jù)庫保存的,縮略圖可以實時訪問的時候用程序生成(節(jié)省很多存儲空間)
實際上,把域名保存在數(shù)據(jù)庫中,非常不利于系統(tǒng)遷移。一旦換個域名的話,原來保存在數(shù)據(jù)庫中的是“wwwabc.om/images/xxxxxx“,因為路徑都在數(shù)據(jù)庫中寫死了。下回換個域名就用不了了。那個時候自己去寫sql語句批量更新字段吧。
幾個術(shù)語:
icp,Internet Content Provider,也就是網(wǎng)絡(luò)內(nèi)容提供者。聯(lián)想到我們運營一個網(wǎng)站需要icp備案了嗎?你自己運營網(wǎng)站,你就是icp服務(wù)商
IDC(Internet Data Center),互聯(lián)網(wǎng)數(shù)據(jù)中心。IDC的概念,目前還沒有一個統(tǒng)一的標(biāo)準。通俗點,就是提供機房托管(服務(wù)器租用和托管),域名注冊之類的。
關(guān)于淘寶的圖片存儲
了解到:淘寶以前使用了商用的存儲。但是沒法滿足需求。據(jù)說,到2010年,淘寶網(wǎng)后端保存著286億張圖片。商用的系統(tǒng)系統(tǒng)沒法滿足需求的時候。他們就自己開發(fā)了一個tfs。大規(guī)模的小文件在磁盤上讀取,需要磁盤磁頭頻繁的尋道和換道。大并發(fā)情況下和大量的操作確實很麻煩。其實借鑒了當(dāng)時google公布的gfs設(shè)計論文。google有相冊服務(wù)。為每個用戶提供上傳圖片存儲。
估計,google是率先實現(xiàn)這種小文件網(wǎng)絡(luò)存儲系統(tǒng)的。
有個觀點比較好:對于老板們而言,往往覺得,用錢能解決的都不算問題。但問題在于,你遇到的問題,別人都沒遇到過。那這個時候你就沒有經(jīng)驗可以參考或者直接拿來使用。只有自己參考一些思路去創(chuàng)造技術(shù)了。
三、關(guān)于圖片進行云存儲(cdn加速)
曾經(jīng)看過這個,這個是比較適合創(chuàng)業(yè)公司的。價格相對便宜
https//wwwupyun.com/
介紹提到,我們在全國各地部署了55個CDN節(jié)點,500多臺服務(wù)器,電信,聯(lián)通,移動和教育網(wǎng)的4線帶寬。
其實,現(xiàn)在的云存儲本質(zhì)就是一個cdn服務(wù)商。你把靜態(tài)的圖片上傳到他提供的服務(wù)器上去(ftp方式上傳或者api形式編寫程序上傳)。他為你做就近節(jié)點訪問。
計費方式:按照流量付費,99元購買100g。怎么算流量。每次訪問文件的大小累加,比如一個1m的文件,訪問一次流量就加1m。
我個人理解,對于圖片的量不大的情況下,使用這種云服務(wù),好處不是節(jié)省存儲空間。你自己的服務(wù)器100g的空間可能創(chuàng)業(yè)型公司都沒用完,不是什么存儲空間不夠用,然后去用云存儲。以前我對cdn比較模糊,有這么點理解,或者以為是分散網(wǎng)站web服務(wù)器流壓力,服務(wù)器分流。這些好處是有的。但是,只要理解了cdn產(chǎn)生的背景和解決的關(guān)鍵問題后,就會明白云存儲關(guān)鍵好處在于:給用戶就近節(jié)點訪問,加速。
我覺得,如果不是出于這個考慮,或者達不到這樣的目的。用其他方案也完全可以替代。何必使用云存儲呢?就是你無非有實力做到全國多個節(jié)點去部署服務(wù),才需要租用cdn來幫你,畢竟他們是規(guī)模產(chǎn)生的效益,專注于解決這個領(lǐng)域。
網(wǎng)站名稱:oracle如何存取照片 sql如何存儲照片
瀏覽地址:http://m.newbst.com/article30/hjhspo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、面包屑導(dǎo)航、搜索引擎優(yōu)化、ChatGPT、靜態(tài)網(wǎng)站、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)