(注冊和建立存儲空間就不介紹了,網上一把一把的資料,自己試着點點也能明白)
作為一個成熟的菜鳥,如果遇到一個新問題,第一步當然是先百度一下。。。
看了N個關於七牛雲的使用的帖子,表示還是蒙圈的,看懂了一部分,但是不系統,理解的不連貫,作為一個凡是要弄個特別明白的死腦筋,於是開始從頭看是研究文檔。。。。(以下都是來自http://developer.qiniu.com/article/index.html#quickstart,經過個人精簡,如有不明,詳情請參閱文檔)
先弄明白原理,才能更好的看懂代碼。
1.三個結構
a.七牛雲存儲服務
b.業務服務器
c.客戶端-------客戶端通常同時是資源的生產方和消費方。客戶端在展示內容時,通常需要先從業務服務器獲取資源的元信息,並得到必要的[下載憑證][downloadtokenHref],然后使用下載憑證從七牛雲存儲服務獲取待展示的資源內容,從而實現一個完整的內容展示過程。
2.業務流程
-
上傳
客戶端在上傳資源到七牛雲存儲之前要先從業務服務器獲取一個有效的上傳憑證,因此需要先后和兩個服務端打交道。
上傳憑證保存在上傳策略( RS文件夾-PutPolicy.cs)(上傳策略具體參數設置 http://developer.qiniu.com/article/developer/security/put-policy.html)
如果有設置回調,則上傳完成時七牛雲存儲會自動發起回調到指定的業務服務器。
-
下載
公開資源不需要對應的下載憑證,客戶端可以直接從七牛雲存儲下載對應資源。私有資源需要對應的下載憑證,因此必須先和業務服務器打交道。
按照實際的使用場景,客戶端對於內容的展示非常類似一個動態網頁的生成過程,因此無論該頁面內容是公開還是私有,均需要從業務服務器獲取展示該頁面的動態布局信息。所以通常顯示過程也是需要先后和業務服務器及七牛雲存儲服務打交道。
於是乎,測試 官方的“簡單上傳”的代碼(http://developer.qiniu.com/code/v6/sdk/csharp.html#io-put)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using Qiniu.Auth; 7 using Qiniu.IO; 8 using Qiniu.IO.Resumable; 9 using Qiniu.RS; 10 11 namespace ConsoleDemo 12 { 13 class UploadDemo 14 { 15 16 private void upload() 17 { 18 //設置賬號的AK和SK 19 Qiniu.Conf.Config.ACCESS_KEY = "Access_Key"; ① 20 Qiniu.Conf.Config.SECRET_KEY = "Secret_Key";② 21 IOClient target = new IOClient(); 22 PutExtra extra = new PutExtra(); 23 //設置上傳的空間 24 String bucket = "bucket_name";③ 25 //設置上傳的文件的key值 26 String key = "yourdefinekey";//上傳成功后的文件名(可以和上傳文件不是同一個名字) ④ 27 28 //普通上傳,只需要設置上傳的空間名就可以了,第二個參數可以設定token過期時間 29 PutPolicy put = new PutPolicy(bucket, 3600); 30 31 //調用Token()方法生成上傳的Token 32 string upToken = put.Token(); 33 //上傳文件的路徑 34 String filePath = "/.../...";⑤ 35 36 //調用PutFile()方法上傳 37 PutRet ret = target.PutFile(upToken, key, filePath, extra); 38 //打印出相應的信息 39 Console.WriteLine(ret.Response.ToString()); 40 Console.WriteLine(ret.key); 41 Console.ReadLine(); 42 } 43 44 static void Main(string[] args) 45 { 46 //實例化UploadDemo對象並調用設置的upload方法 47 UploadDemo Upload = new UploadDemo(); 48 Upload.upload(); 49 } 50 } 51 }
以上5處需要修改為自己的內容
看了半天都是蒙圈,最后感覺其實上傳的過程就是兩步、兩步、兩步!!!!
1.生成TOKEN(上傳憑證upload-token,詳情見http://developer.qiniu.com/article/developer/security/upload-token.html)
構造上傳策略1json化=>
2URL安全的Base64編碼=>
3使用SecretKey計算HMAC-SHA1簽名=>
4再進行一次URL安全的Base64編碼=>
5最終拼接成uploadToken=>
總結,②是用於加密上傳策略的,①③是構造上傳策略,①②③一起生成token,④⑤和token一起作為PutFile()方法的上傳參數。
具體到程序中,
Mac就是計算“七牛認證”的類(包括計算方法,讓Token方法調用)
Mac的sign方法實現了上面第三步的“SecretKey計算HMAC-SHA1簽名”&第四步
Mac的SignWithData調用了sign並實現上面第五步,拼接形成最后的上傳憑證(token)
2.調用“ IOClient”的“PutFile()”方法上傳
特別注意:如果注冊空間的時候,選擇了“華北”,那么需要增加一行代碼,否則怎么上傳都不成功。。。。
1 Qiniu.Conf.Config.UP_HOST = "http://up-z1.qiniu.com";
開個控制台,調用UploadDemo.upload
1 UploadDemo Upload = new UploadDemo(); 2 Upload.upload();
查看空間里有沒有這個文件(空間-內容管理),如果有就說明“簡單上傳”測試成功了。
接下來,就是搞定ueditor中上傳圖片到七牛雲。
由於ueditor使用的是流,所以只需要把PutFile方法改為使用Put方法,(IOClient中有個Put方法可以使用流,如下)
public PutRet Put(string upToken, string key, System.IO.Stream putStream, PutExtra extra) { if (!putStream.CanRead) { throw new Exception("read put Stream error"); } PutRet ret; NameValueCollection formData = getFormData(upToken, key, extra); try { CallRet callRet = MultiPart.MultiPost(Config.UP_HOST, formData, putStream); ret = new PutRet(callRet); onPutFinished(ret); return ret; } catch (Exception e) { ret = new PutRet(new CallRet(HttpStatusCode.BadRequest, e)); onPutFinished(ret); return ret; } }
代碼改為:
using Qiniu.IO; using Qiniu.RS; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace qiniu { public class UploadDemo { public void upload() { Qiniu.Conf.Config.ACCESS_KEY = ""; Qiniu.Conf.Config.SECRET_KEY = ""; Qiniu.Conf.Config.UP_HOST = "http://up-z1.qiniu.com"; IOClient target = new IOClient(); PutExtra extra = new PutExtra(); //設置上傳的空間 String bucket = ""; //設置上傳的文件的key值 String key = "222.jpg"; //普通上傳,只需要設置上傳的空間名就可以了,第二個參數可以設定token過期時間 PutPolicy put = new PutPolicy(bucket, 3600);//調用Token()方法生成上傳的Token string upToken = put.Token(); //上傳文件的路徑 String filePath = @"E:\chaye.jpg"; FileStream fs=new FileStream (filePath,FileMode.Open,FileAccess.Read); //調用PutFile()方法上傳 // PutRet ret = target.PutFile(upToken, key, filePath, extra); PutRet ret=target.Put(upToken,key,fs,extra); //打印出相應的信息 Console.WriteLine(ret.Response.ToString()); Console.WriteLine(ret.key); Console.ReadLine(); } } }
既然方法試驗成功,最后就是結合ueditor,改造代碼
ueditor的IOClient.cs的Put方法添加
UploadHandler.cs中改造Process方法
1 public override void Process() 2 { 3 byte[] uploadFileBytes = null; 4 string uploadFileName = null; 5 6 if (UploadConfig.Base64) 7 { 8 uploadFileName = UploadConfig.Base64Filename; 9 uploadFileBytes = Convert.FromBase64String(Request[UploadConfig.UploadFieldName]); 10 } 11 else 12 { 13 var file = Request.Files[UploadConfig.UploadFieldName]; 14 uploadFileName = file.FileName; 15 if (!CheckFileType(uploadFileName)) 16 { 17 Result.State = UploadState.TypeNotAllow; 18 WriteResult(); 19 return; 20 } 21 if (!CheckFileSize(file.ContentLength)) 22 { 23 Result.State = UploadState.SizeLimitExceed; 24 WriteResult(); 25 return; 26 } 27 28 uploadFileBytes = new byte[file.ContentLength]; 29 try 30 { 31 file.InputStream.Read(uploadFileBytes, 0, file.ContentLength); 32 } 33 catch (Exception) 34 { 35 Result.State = UploadState.NetworkError; 36 WriteResult(); 37 } 38 } 39 40 Result.OriginFileName = uploadFileName; 41 42 //上傳到七牛雲 43 44 string qiNiuFileName=CommonHelper.CalcMD5(uploadFileBytes)+Path.GetExtension(uploadFileName);
//自己封裝了一個MD5的方法,隨意,可以不加,這里就是為了盡量避免重名 45 49 var savePath = PathFormatter.Format(uploadFileName, UploadConfig.PathFormat); 50 var localPath = Server.MapPath(savePath); 51 try 52 { 53 Qiniu.Conf.Config.ACCESS_KEY = ""; 54 Qiniu.Conf.Config.SECRET_KEY = ""; 55 Qiniu.Conf.Config.UP_HOST = ""; 56 IOClient target = new IOClient(); 57 PutExtra extra = new PutExtra(); 58 //設置上傳的空間 59 String bucket = ""; 60 //設置上傳的文件的key值 61 String key = qiNiuFileName;//1 62 63 //普通上傳,只需要設置上傳的空間名就可以了,第二個參數可以設定token過期時間 64 PutPolicy put = new PutPolicy(bucket, 3600); 65 66 67 //調用Token()方法生成上傳的Token 68 string upToken = put.Token(); 69 //上傳文件的路徑 70 MemoryStream ms = new MemoryStream(uploadFileBytes); 71 72 //調用PutFile()方法上傳 73 // PutRet ret = target.PutFile(upToken, key, filePath, extra); 74 PutRet ret = target.Put(upToken, key,ms, extra); 75 76 Result.Url = "外鏈默認域名" + qiNiuFileName; 77 78 Result.State = UploadState.Success; 79 80 //PutPolicy policy = new PutPolicy(bucket, 3600); 81 //string upToken = policy.Token(); 82 //Settings setting = new Settings(); 83 //ResumablePutExtra extra = new ResumablePutExtra(); 84 //ResumablePut client = new ResumablePut(setting, extra); 85 //CallRet callRet = client.PutFile(upToken, new byte[0] { }, ""); 86 //if (callRet.OK) 87 //{ 88 89 //} 90 91 } 92 catch (Exception e) 93 { 94 Result.State = UploadState.FileAccessError; 95 Result.ErrorMessage = e.Message; 96 } 97 finally 98 { 99 WriteResult(); 100 } 101 }
參考https://segmentfault.com/a/1190000002462516
注意:導致瀏覽器訪問的時候(編譯並不報錯),顯示 “文件訪問出錯,檢查權限”,F12看上傳后response報文,未找到newtonjson 4.5.0.0。
原因:因為之前手動添加過Newtonsoft.Json.dll(4.5.0.0),跟ueditor-net- Bin目錄的newtonJson版本 不一致(9.0.0.0)。
解決方法:在web.config的<configuration>節點下添加,只需要添加一次,之后刪除都可以。
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <bindingRedirect oldVersion="4.5.0.0-6.0.0.0" newVersion="9.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime>
猜想,關於newtonJSON版本的問題,都可以通過上面代碼解決。
補充,如果需要兩個版本的dll引用
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" /> <codeBase version="6.0.0.0" href="D:\documents\visual studio 2012\Projects\NDT\NDTDecive\NDTDevice.Admin\ueditor\net\Bin\Newtonsoft.Json.dll" /> <codeBase version="9.0.0.0" href="D:\documents\visual studio 2012\Projects\NDT\NDTDecive\NDTDevice.Admin\qiniu\Newtonsoft.Json.dll" /> </dependentAssembly> </assemblyBinding> </runtime>