引文
B/S模式下,由於瀏覽器的沙箱系統,瀏覽器無法直接訪問用戶本地的系統資源,那麼問題來了:
如果要做一個超市收銀系統,怎麼使用掃碼器呢?
如果要做一個網吧管理系統,怎麼使用讀卡器呢?
如果要做一個系統要調用打印機、密碼鍵盤、高拍儀等外部設備呢?
如果要讀取用戶機上已知路徑下的文件呢?
這個時候就要用到ActiveX控件了,掃碼器、讀卡器、高拍儀等外部設備對外提供了ActiveX控件,ActiveX控件對外發布了外設調用接口。瀏覽器只要創建一個控件對象就可以調用接口驅動外設了,具體的實現在後文。
目錄
1、介紹瀏覽器的“沙箱”安全機制
2、介紹ActiveX控件
3、利用VC++6.0開發OCX控件
4、WEB端調用OCX控件的接口
5、OCX控件打包發佈
一、沙箱(SandBox)--瀏覽器的一種安全機制
沙箱是一種隔離對象/線程/進程的機制,控制瀏覽器訪問系統資源的權限,從而達到保護用戶的系統不被網頁上的惡意軟件侵入、保護用戶系統的輸入事件(鍵盤/鼠標)不被監視、保護用戶系統中的文件不被偷取等目的。最初的瀏覽器沙箱是基於Hook實現的,後來的Chrome沙箱是利用操作系統提供的一些安全機制實現的。
二、ActiveX控件
ActiveX控件是可以在應用程序和網絡中計算機上重複使用的程序對象。ActiveX控件可由不同語言的開發工具開發,包括C++和Visual Basic或PowerBuilder,甚至一些技術性語言如VBScript。
常用的ActiveX控件由DLL和OCX兩種,其中DLL可以是函數接口,也可以是對象接口,OCX是DLL中的一種純面向對象的控件,一般跨語言都用OCX控件。
三、利用VC++6.0開發OCX控件
案例:將用戶PC機中已知路徑下的JPG圖片轉成base64字符串返回
接口:string image2Base64(fullPath)
說明:輸入圖片文件完整路徑,獲取圖片的base64字符串
第一步:創建項目ImgTools:
*提示:工程選擇“MFC ActiveX ControlWizard”
點擊確定:
直接點擊完成:
點擊確定,項目創建成功,查看FileView目錄:
第二步:添加base64編碼和解碼用的工具類ZBase64:
查看ClassView目錄,右鍵項目節點,選擇New Class,類的類型選擇Generic Class,類名稱ZBase64ZBase64類創建成功後,右鍵類節點,選擇Add Member Function,爲這個類,新增兩個方法,分別是編碼和解碼(我們只會用到編碼):
方法1:函數類型:CString;函數描述:Decode(const char *Data, int DataByte, int &OutByte)
CString ZBase64::Decode(const char *Data, int DataByte, int &OutByte)
{
//解碼錶
const char DecodeTable[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62, // '+'
0, 0, 0,
63, // '/'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
0, 0, 0, 0, 0, 0,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
};
//返回值
CString strDecode;
int nValue;
int i= 0;
while (i < DataByte)
{
if (*Data != '\r' && *Data!='\n')
{
nValue = DecodeTable[*Data++] << 18;
nValue += DecodeTable[*Data++] << 12;
strDecode+=(nValue & 0x00FF0000) >> 16;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++] << 6;
strDecode+=(nValue & 0x0000FF00) >> 8;
OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++];
strDecode+=nValue & 0x000000FF;
OutByte++;
}
}
i += 4;
}
else// 回車換行,跳過
{
Data++;
i++;
}
}
return strDecode;
}
方法2:函數類型:CString;函數描述:Encode(const char *Data, int DataByte)
CString ZBase64::Encode(const char *Data, int DataByte)
{
//編碼表
const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//返回值
CString strEncode;
unsigned char Tmp[4]={0};
int LineLength=0;
for(int i=0;i<(int)(DataByte / 3);i++)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
Tmp[3] = *Data++;
strEncode+= EncodeTable[Tmp[1] >> 2];
strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
strEncode+= EncodeTable[Tmp[3] & 0x3F];
if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
}
//對剩餘數據進行編碼
int Mod=DataByte % 3;
if(Mod==1)
{
Tmp[1] = *Data++;
strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
strEncode+= "==";
}
else if(Mod==2)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
strEncode+= "=";
}
return strEncode;
}
第三步:新增控件對外的接口GetImgBase64:
這裏有3個文檔需要修改,1、ImgTools.odl文檔,添加代碼:[id(1)] BSTR GetImgBase64(BSTR filePath);
2、ImgToolsCtl.h文檔,添加代碼:
afx_msg BSTR CImgToolsCtrl::GetImgBase64(LPCTSTR filePath);
dispidGetImgBase64 = 1L,
3、ImgTools.cpp文檔,添加代碼:
DISP_FUNCTION(CImgToolsCtrl, "GetImgBase64", GetImgBase64, VT_BSTR, VTS_BSTR )
ImgTools.cpp文檔,還需添加該接口的實現
BSTR CImgToolsCtrl::GetImgBase64(LPCTSTR filePath)
{
CString strResult = "123";
return strResult.AllocSysString();
}
第四步:實現接口的圖片Base64編碼:
BSTR CImgToolsCtrl::GetImgBase64(LPCTSTR filePath)
{
CString strResult;
FILE * fImg = fopen (filePath, "rb") ;
if (!fImg)
{
strResult = "file is not exist!";
}
else
{
CString img;
fseek(fImg,0L,2);
int sumLen = ftell(fImg);
rewind(fImg);
char ch;
for(int i = 0; i < sumLen; i ++)
{
ch=fgetc(fImg);
img += ch;
}
strResult = zBase.Encode(img.GetBuffer(sumLen), sumLen);
fclose(fImg);
}
return strResult.AllocSysString();
}
第五步:組裝控件,從debug文件夾中獲取生成的ocx控件
上面4步過後,全部保存,然後工具欄->組建->全部重建,即可在項目所在路徑下的debug目錄中看到ocx控件:四、WEB端調用OCX控件的接口
第一步:註冊OCX控件
在ImgTools.ocx同級目錄下,新增reg.bat文件文本形式打開reg.bat文件後,輸入一條指令:RegSvr32 ImgTools.ocx
保存文件後,雙擊reg.bat文件即可成功註冊ImgTools控件:
第二步:編寫測試網頁
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>測試OCX</title>
</head>
<body>
<object id='ocxObj' name='ocxObj' classid='clsid:130A16C5-5374-4E3D-9071-063FE3AC0205' style='display:none'></object>
<input type="button" value="測試" onclick="test()" />
<br/><br/>
圖片完整路徑:<input type="text" id="path" />
<br/><br/>
<textarea rows="8" style="width:700px" id="showMsg">123123</textarea>
<script type="text/javascript">
function test() {
var path = document.getElementById("path").value;
var str = ocxObj.GetImgBase64(path);
document.getElementById("showMsg").value = str;
}
</script>
</body>
</html>
其中“130A16C5-5374-4E3D-9071-063FE3AC0205”是ImgTools.odl文檔中最後一個,即第四個uuid值。