圖片存儲到cassandra數據庫的方案
1、創建一個測試的CF
create Column family ImagesFile with comparator=UTF8Type and default_validation_class=UTF8Type and key_validation_class=UTF8Type and column_metadata= [ {column_name: ImagesFileId , validation_class: UTF8Type,index_type: KEYS}, {column_name: FileName, validation_class: UTF8Type}, {column_name: FileByteDatas, validation_class: UTF8Type} ];2、服務端代碼如下:
package com.reach.leekexi.cassandra.hecter;import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.Map;
import javax.imageio.ImageIO;
public class ImagesCassandraClient {
public static String hosts = "192.168.1.20:9160"; public static String clusterName = "Test Cluster"; public static String keyspaceName = "CasImage"; public static String columnFamily = "ImagesFile";
@SuppressWarnings({ "rawtypes" }) public static void main(String[] args) {
// 參數裝載 CassandraParas ps = new CassandraParas(); ps.setHosts(hosts); // 注解數據 ps.setClusterName(clusterName);// 群集名稱 ps.setKeyspaceName(keyspaceName);// 鍵空間 ps.setColumnFamily(columnFamily);// 列族
// cassandra客戶端API接口實例 CassandraClient cc = new CassandraClient(ps);
boolean inf = false;// 插入標記 String key = "1";// 插入的Key
// 測試多個字段插入和讀取 String[] columnNames = { "ImagesFileId", "FileName" }; String[] columnValues = { "1", "http://avatar.csdn.net/3/1/8/3_jemlee2002.jpg" }; inf = cc.insertMultiColumn(key, columnNames, columnValues);
if (inf)// 如果插入成功則測試打印出來 { Map map = new HashMap(); map = cc.getMultiColumn(key, columnNames); for (int i = 0; i < map.size(); i++) System.out.println(columnNames[i] + " : "
- map.get(columnNames[i])); } else { System.out.println("操作數據失敗,CF=" + columnFamily); }
//把圖片存儲到Cassandra數據庫 String columnName = "FileByteDatas"; String columnValue = parserFileNet("http://avatar.csdn.net/3/1/8/3_jemlee2002.jpg","jpg"); inf = cc.insertOneColumn(key, columnName, columnValue); if (inf) { System.out.println(cc.getOneColumn(key, columnName)); }
//把數據庫的種的圖片數據還原成圖片 //如果在C盤下看到了和http://avatar.csdn.net/3/1/8/3_jemlee2002.jpg一個樣的圖片數據,證明數據處理成功。 columnValue = cc.getOneColumn(key, columnName); String localpath = "c:\3_jemlee2002.jpg"; String type = "png"; boolean ref = revertImage(columnValue,localpath,type); if(ref) System.out.println("創建文件:" + localpath + " 成功."); else System.out.println("創建文件:" + localpath + " 失敗.");
}
/**
- 網絡文件存儲
- @param URLName 網絡圖片地址
- @param type 圖片類型
- @return String 轉換結果
@throws
*/
public static String parserFileNet(String URLName,String type) {
String res = null;
try {int HttpResult = 0; // 服務器返回的狀態 URL url = new URL(URLName); // 創建URL URLConnection urlconn = url.openConnection(); // 試圖連接并取得返回狀態碼 urlconn.connect(); HttpURLConnection httpconn = (HttpURLConnection) urlconn; HttpResult = httpconn.getResponseCode(); System.out.println(HttpResult); if (HttpResult != HttpURLConnection.HTTP_OK) // 不等于HTTP_OK則連接不成功 System.out.print("fail"); else { BufferedInputStream bis = new BufferedInputStream(urlconn.getInputStream()); BufferedImage bm = ImageIO.read(bis); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ImageIO.write(bm, type, bos); bos.flush(); byte[] data = bos.toByteArray(); res = byte2hex(data); bos.close(); }
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
/**
- 本地文件存儲
- @param filepath 本地文件路徑
- @return String 轉換結果
*/ public static String parserFileLocal(String filepath) { File file = new File(filepath); byte[] bfile = new byte[10240]; String filestr = ""; try { InputStream a = new FileInputStream(file); a.read(bfile); filestr = byte2hex(bfile); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return filestr; }
/**
- 把Cassandra數據庫中的圖片數據還原成圖片
- @param data 生成圖片的二進制字符串
- @param fileName 圖片名稱(完整路徑)
- @param type 圖片類型
@return
*/
public static boolean revertImage(String data, String fileName,String type) {BufferedImage image = new BufferedImage(300, 300,BufferedImage.TYPE_BYTE_BINARY);
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
boolean rf = false; try {ImageIO.write(image, type, byteOutputStream); byte[] bytes = hex2byte(data); RandomAccessFile file = new RandomAccessFile(fileName, "rw"); file.write(bytes); file.close(); rf = true;
} catch (IOException e) {
rf = false;e.printStackTrace();
}
return rf; }
/**
- 二進制轉字符串
- @param
- @return */ public static String byte2hex(byte[] b) {
String hs = ""; String stmp = ""; for (int n = 0; n < b.length; n++) { stmp = (java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length() == 1) hs = hs + "0" + stmp; else hs = hs + stmp; } return hs; }
/**
- 字符串轉二進制
- @param str
- @return */ public static byte[] hex2byte(String str) {
if (str == null) return null;
str = str.trim(); int len = str.length(); if (len == 0 || len % 2 == 1) return null; byte[] b = new byte[len / 2]; try { for (int i = 0; i < str.length(); i += 2) { b[i / 2] = (byte) Integer .decode("0x" + str.substring(i, i + 2)).intValue(); } return b; } catch (Exception e) { return null; } }
}</pre></strong>
3、總結
以上代碼高效的實現圖片(含網絡上的和本地的)存儲到Cassandra數據的過程。特別提出,該方案中,中間并不需要中間暫存圖片到本地,而是直接從http協議上獲取圖片流數據,這樣極大的提高圖片的處理速度。