接到一個任務,有2台機器,其中有一台機器A有每天資料庫的備份,我想另外的一台機器B定時從A中copy到B的制定目錄,A不共用資料庫備份的目錄。考慮到FTP方式無法跨越NAT(網路位址轉譯),而HTTP方式在安全性和可靠性方面都得不到保證,在檔案較大時也會有一定的限制。決定採用一種基於HTTP協議,編寫用戶端和伺服器端程式,在一個用戶端用HttpWebRequest對象向指定的URL發送POST和GET請求,在伺服器端通過程式接受請求,進行檔案傳輸,這樣,發送和接收都由自己編寫的程式進行控制,可以方便地實現諸如身分識別驗證、資料加密和斷點續傳等功能,同時可以穿越防火牆和NAT。這樣做就可以實現在.Net中跨Internet的檔案加密傳輸。
在.net中實現跨Internet的檔案加密傳輸的程式源碼 一、資料上傳1.用戶端代碼 //從文字框中獲得檔案的全稱,含路徑名string strFilePath=txUpFile.Text;//獲得檔案的長度FileInfo fi=new FileInfo(strFilePath);long lFileLength=fi.Length;//獲得檔案名稱 string strFileName=strFilePath.Substring(strFilePath.LastIndexOf("//")+1); //建立HttpWebRequest對象,傳入路徑名,將檔案名稱和長度作為參數傳給伺服器端HttpWebRequest objRequest=(HttpWebRequest)HttpWebRequest.Create(string. Format(@"{0}?FileName={1}&FileLength={2}",txUpURL.Text,strFileName, lFileLength.ToString()));//定義Request對象的方法為"post"objRequest.Method="POST";//定義Request對象的內容類型為"application/octet-stream"objRequest.ContentType="application/octet-stream";//定義請求內容的長度objRequest.ContentLength=((int)(lFileLength/8+1))*8;//定義一個請求的流Stream reqStream=objRequest.GetRequestStream();//用DES演算法加密此請求流byte[] desKey={1,0,1,1,5,6,7,8};byte[] desIV={1,2,3,4,5,6,7,8};DES des=new DESCryptoServiceProvider();
CryptoStream encStream=new CryptoStream(reqStream,des.CreateEncrytor(desKey,desIV),CryptoStreamMode.Write);
//定義記憶體緩衝區用於檔案的讀寫
int iBufferSize=4095;byte[] buffer=new byte[iBufferSize];//開啟檔案,準備讀取FileStream fileStream=new FileStream(strFilePath,FileMode.Open,FileAccess.Read);int iReadLength=0;//將檔案內容讀入緩衝區
iReadLength=fileStream.Read(buffer,0,buffer.Length);
while(iReadLength!=0) {
//將讀出的檔案內容寫入加密流
encStream.Write(buffer,0,iReadLength);
iReadLength=fileStream.Read(buffer,0,buffer.Length);
}
//關閉請求的流
encStream.Close();
reqStream.Close();
fileStream.Close();
//向伺服器提出請求並獲得結果3
HttpWebResponse sp=(HttpWebResponse)objRequest.GetResponse();
string strContent="";
int iLen=(int)sp.ContentLength;
if(iLen>0) {
//將結果流寫入到二進位流bContent中
Stream resStream=sp.GetResponseStream();
byte[] bContent=new byte[sp.ContentLength];
resStream.Read(bContent,0,iLen);
sp.Close();
//由於結果是一個位元據,必須將結果解碼成字串
char[] charContent=new char[sp.ContentLength];
Text.Decoder dc=Text.Encoding.UTF8.GetDecoder();
int charLen=dc.GetChars(bContent,0,bContent.Length,charContent,0);
foreach(char c in charContent) strContent+=c.ToString();
}
2.伺服器端代碼
//判斷請求的ContentType,過濾非法請求
if(Request.ContentType!="application/octet-stream") return;
//獲得上傳得檔案名稱和長度
string strFileName=Request.QueryString["FileName"];
int iFileLength=Request.TotalBytes;
//構造伺服器端檔案名稱
string strFilePath=Server.MapPath(".")+IO.Path.DirectorySeparatorChar+"Upload"+IO.Path.DirectorySeparatorChar+strFileName;
//判斷檔案是否存在
if(File.Exists(strFilePath)) {
//如果檔案存在,返迴文件名和檔案長度
FileInfo fi=new FileInfo(strFilePath);
long lFileLength=fi.Length;
Response.Write("File["+strFileName+"]Exists!Length="+lFileLength.ToString());
Response.End();
}
//如果檔案不存在,開啟檔案流建立該檔案
FileStream fileStream=File.Create(strFilePath,iFileLength);
//用DES演算法解密該檔案流
byte[] desKey={1,0,1,1,5,6,7,8};byte[] desIV={1,2,3,4,5,6,7,8};DES des=new DESCryptoServiceProvider();CryptoStream desStream=new CryptoStream(fileStream,des.CreateDecryptor(desKey,desIV),CryptoStreamMode.Write);//定義記憶體緩衝區大小int iBufferSize=4095;//讀取請求流並寫入檔案中byte[] buffer=new byte[iBufferSize];int iReadLength=0;iReadLength=Request.InputStream.Read(buffer,0,buffer.Length);while(iReadLength>0) { desStream.Write(buffer,0,iReadLength); desStream.Flush(); iReadLength=Request.InputStream.Read(buffer,0,buffer.Length);}desStream.Flush();desStream.Close();fileStream.Close();//返回結果Response.Write("File["+strFileName+"]UploadSuccess!");Response.End(); 二、資料下載1.用戶端代碼//擷取下載檔案名稱string strFileName=txDownFile.Text;//定義檔案位移量int iOffset=0;//建立HttpWebRequest對象,傳入路徑名,將檔案名稱和位移量作為參數傳給伺服器HttpWebRequest objRequest=(HttpWebRequest)HttpWebRequest.Create(string. Format(@"{0}?FileName={1}&Offset={2}",txDownURL.Text,strFileName,iOffset));//定義Request對象的方法為"get"objRequest.Method="GET";//定義Request對象的內容類型為"application/octet-stream"objRequest.ContentType="application/octet-stream"//獲得請求結果HttpWebResponse sp=(HttpWebResponse)objRequest.GetResponse();Stream resStream=sp.GetResponseStream();string strFilePath=txDownPath.Text;//如果檔案存在,則刪除if(File.Exists(strFilePath)) { File.Delete(strFilePath);}//建立檔案int iBufferSize=4095;FileStream fileStream=File.Create(strFilePath);//解密返回的流 byte[] desKey={1,0,1,1,5,6,7,8};byte[] desIV={1,2,3,4,5,6,7,8};DES des=new DESCryptoServiceProvider();CryptoStream decStream=new CryptoStream(resStream,des.CreateDecryptor(desKey,desIV),CryptoStreamMode.Read);byte[] buffer=new byte[iBufferSize];int iReadLength=0;//讀取返迴流iReadLength=decStream.Read(buffer,0,buffer.Length);while(iReadLength>0) { //寫入檔案流中 fileStream.Write(buffer,0,iReadLength); iReadLength=decStream.Read(buffer,0,buffer.Length);}fileStream.Flush();decStream.Close();fileStream.Close();resStream.Close();return "File["+strFileName+"]Download Success!";
2.伺服器端代碼
//獲得上傳的檔案名稱和位移量
string strFileName=Request.QueryString["FileName"];
long lOffset=Convert.ToInt64(Request.QueryString["Offset"]);
//構造檔案全路徑名
string strFilePath=Server.MapPath(".")+IO.Path.DirectorySeparatorChar+"Download"+IO.Path.DirectorySeparatorChar+strFileName;
//若檔案不存在,則返回錯誤資訊
if(!File.Exists(strFilePath)) {
Response.Clear();
Response.Write("File["+strFileName+"]Not Exists!");
Response.End();
}
//開啟檔案
IO.FileStream fileStream=new IO.FileStream(strFilePath,IO.FileMode.Open,IO.FileAccess.Read,IO.FileShare.Read);
//根據上傳的位移量參數設定位移量
if(lOffset>0)
fileStream.Seek(lOffset,IO.SeekOrigin.Begin);
//定義輸出資料流
Stream resStream=Response.OutputStream;
//用DES演算法加密此資料流
byte[] desKey={1,0,1,1,5,6,7,8};byte[] desIV={1,2,3,4,5,6,7,8};DES des=new DESCryptoServiceProvider();CryptoStream encStream=new CryptoStream(resStream,des.CreateDecryptor(desKey,desIV),CryptoStreamMode.Write);//定義輸出檔案流的頭Response.ContentType="application/octet-stream";Response.AddHeader("Content-Disposition","attachment;filename="+strFileName);int iBufferSize=4095;byte[] buffer=new byte[iBufferSize];int iReadLength=0;//讀取檔案iReadLength=fileStream.Read(buffer,0,buffer.Length);while(iReadLength>0) { //寫入輸出資料流 encStream.Write(buffer,0,iReadLength); iReadLength=fileStream.Read(buffer,0,buffer.Length);}encStream.Flush();resStream.Flush();//關閉流encStream.Close();resStream.Close();fileStream.Close();//Response.Flush();//結束輸出Response.End();