Upload files to aliyunOSS with bootstrap-fileinput

来源:http://www.cnblogs.com/newton/archive/2016/11/17/6066020.html
-Advertisement-
Play Games

本文主要涉及兩個概念: 阿裡雲OSS:對象存儲(Object Storage Service,簡稱OSS),是阿裡雲對外提供的海量、安全和高可靠的雲存儲服務。 bootstrap-fileinput:An enhanced HTML 5 file input for Bootstrap 3.x wi ...


本文主要涉及兩個概念:

  • 阿裡雲OSS:對象存儲(Object Storage Service,簡稱OSS),是阿裡雲對外提供的海量、安全和高可靠的雲存儲服務。
  • bootstrap-fileinput:An enhanced HTML 5 file input for Bootstrap 3.x with file preview for various files, offers multiple selection, and more.

客服稱OSS不限制上下行流量,而且不占用ECS帶寬,所以將靜態文件存放在OSS是個不錯的選擇。除了放置站點引用的資源文件外,主要用於用戶文件的上傳。阿裡雲提供了Web端直傳方式,文件不經過站點伺服器,不影響站點的性能和帶寬。真正擼代碼時,遇到了不少坑,而官方文檔秉承阿裡一貫的程式員風格,天馬行空毫不連貫,博主東拼西湊才理順各細節,關鍵點記錄如下,供需要的朋友參考。


阿裡官方沒有提供.NET的demo,找到Post Object,該文檔描述了提交的各參數。進行Post操作要求對bucket有寫許可權,如果bucket為public-read-write,可以不上傳簽名信息,否則要求對該操作進行簽名驗證。與Put操作不同,Post操作使用AccessKeySecret對policy進行簽名計算出簽名字元串作為Signature表單域的值,OSS會驗證該值從而判斷簽名的合法性(不需要遵循用戶簽名驗證(Authentication)的規定,另外在header或url中加上簽名)。policy又是啥呢?Post請求的policy表單域用於驗證請求的合法性。 policy為一段經過UTF-8和base64編碼的JSON文本,聲明瞭Post請求必須滿足的條件(文件大小、一些http頭等,還有該條件的過期時間)。雖然對於public-read-write的bucket上傳時,post表單域為可選項(其它情況,因為需要簽名驗證,所以是必選項),也強烈建議使用該域來限制Post請求。

so,第一步,構造Post條件,對於不同bucket,可以有不同的條件,可以寫在web.config中,如果經常變動,也可以寫在資料庫中方便管理。

 然後,給前端提供一個獲取policy的介面,代碼就不貼了,使用官方提供的SDK,很簡單。這裡假設介面名稱為GetPolicyForOSSUpload,返回結果是:

Data = new ModelForOSSUpload
{
    AccessKeyId = aliyunconfig.AccessKeyId,
    PolicyBase64 = encodedPolicy,
    Signature = signature,
    Expiration = expiration
}

註意,expiration已經被用於構造PolicyBase64了,這裡又單獨給個欄位返回,是給前端用的,在有效時間內,不用再調該介面,能減輕伺服器壓力一點是一點。

前端js是這樣的:

 1 _getUploadPreSetting: function (bucketKey, policyName) {
 2     var presetting = {}, error = {}, self = this;
 3     var inner_getUploadPreSetting = function () {
 4         var now = new Date();
 5         if (!presetting.Expiration || presetting.Expiration < now) {
 6             presetting = {};
 7             error = {};
 8             $.ajax({
 9                 url: self._ossOpts.uploadPreSettingUrl,
10                 type: 'GET',
11                 async: false,
12                 data: { bucketKey: bucketKey, policyName: policyName },
13                 success: function (result) {
14                     if (result.IsSucceed) {
15                         presetting = result.Data;
16                         //應付/Date(1460817323032)/這種奇葩格式
17                         presetting.Expiration = eval('new ' + (presetting.Expiration.replace(/\//g, '')));
18                     }
19                     else {
20                         error = result;
21                     }
22                 },
23                 error: function (xhr, msg) {
24                     error = { IsSucceed: false, Message: msg };
25                 }
26             });
27         }
28         return presetting || error;
29     };
30     return inner_getUploadPreSetting;
31 }

此處用了閉包,這是因為不同的policy,我們以bucketKey和policyName進行區分(看貼出來的web.config片段),如果一個頁面需要多個policy,每個policy都要對應一個變數,數量不定的情況下,我們也不能硬編碼,同時為了讓它們互不影響,就採用了閉包的方式。調用如下:

var getUploadPreSetting = this._getUploadPreSetting(this._ossOpts.bucketKey, this._ossOpts.policyName);
var presetting = getUploadPreSetting();

policy的部分到此為止,下麵我們來看下bootstrap-fileinput這個組件,並對它進行一點點改造,以便於符合OSS的上傳規則。


除了文件數據,提交時還要附加OSS要求的一些表單域,比如剛纔講的policy、Signature,還可以給每個文件加上cache-Control、callback(上傳成功後,OSS回調我們的介面地址)等。我們在初始化bootstrap-fileinput(下稱fileinput)時可以傳入一個uploadExtraData配置項(函數或對象),在上傳每個文件時,fileinput會調用uploadExtraData,將獲取到的數據附加到文件數據後一起上傳。然而這就存在一個問題了,OSS文檔中說“文件或文本內容,必須是表單中的最後一個域。”,否則會返回“The bucket POST must contain the specified 'key'. If it is specified, please check the order of the fields”的錯誤信息。

題外話:關於表單域順序的說明,以前文檔中並沒有,還是博主在一次工單提交和差點投訴後才加上去的,當時很奇怪難道沒人遇到過,還是說這樣用OSS的人不多?另外在和客服扯皮的同時,博主也上網搜了一把,發現AWS的用戶竟然也遇到類似問題,請看 InvalidArgumentBucket POST must contain a field named 'key'. If it is specified, please check the order of the fields.keyB,連返回的錯誤消息都大同小異,博主大膽猜測,阿裡雲和AWS的數據存儲用的是同一套組件,還是開源的,博主知識淺陋,有知道的朋友說一聲。

於是只能去看fileinput的源碼了,幸好它是開源的,我們只需要改動一下_uploadSingle函數的末尾:

self._uploadExtra(previewId, i); //新加
formdata.append(self.uploadFileAttr, files[i], self.filenames[i]); //文件數據
formdata.append('file_id', i);
self._ajaxSubmit(fnBefore, fnSuccess, fnComplete, fnError, previewId, i, true); //也要改造下_ajaxSubmit,傳入true表示額外數據不再附加

_ajaxSubmit也改造了下,圓圈內為新加:

fileinput改造完畢,so easy!那麼當上傳成功後,我們一般都是要對應用數據做一些處理,比如更新資料庫中的url地址什麼的,我們可以獲取響應信息,然後再調用相應的後臺介面,OSS也提供了直接回調的方式,後者能傳遞更多關於文件的信息,並且在構造callback時可自定義參數,因此更靈活,方便後臺回調介面的數據處理,具體可看Callback


下例,前端js:

callback:{
    "callbackUrl":GlobalConfig.siteurl+'Merchandise/SetMerchandisePicUrl',
    "callbackBody":"merchandiseid="+vm.merchandise.BasicInfo.ID+"&picname=${object}"
}

後端回調介面:

 1 [AllowAnonymous]
 2 public async Task<ActionResult> SetMerchandisePicUrl(int merchandiseid, string picname)
 3 {
 4     var aliyunconfig = MvcApplication.AliyunConfig;
 5     var bucket = aliyunconfig.OSS.Buckets["merchandise_pictures"];
 6     var picUri = $"http://{ bucket.Value}.{aliyunconfig.OSS.ImgEndpoint}/{picname}";
 7     await MerchandiseContext.AppendPicUri(merchandiseid, picUri);
 8     return this.Json(new
 9     {
10         initialPreview = new string[] { picUri },                
11         initialPreviewConfig = new List<object> {
12                 new {
13                     caption = picname,
14                     //width ="160px", //並沒有什麼用
15                     url =Url.Action("RemoveMerchandisePicUrl"),
16                     extra = new {picUri= picUri,merchandiseid = merchandiseid}
17                 }
18         }
19     });
20 }

介面允許匿名,便於OSS調用,為了防止惡意調用,最好進行簽名校驗。fileinput根據返回結果判斷是否上傳成功(沒有error屬性表示上傳成功),若成功且結果里有initialPreview[和initialPreviewConfig]等屬性,則將這些屬性應用到對應文件顯示。特別註意initialPreviewConfig中的url和extra屬性,表示刪除該文件時調用的介面和傳遞的參數。


其它參考資料:

理解DOMString、Document、FormData、Blob、File、ArrayBuffer數據類型

Web 前沿——HTML5 Form Data 對象的使用

 

轉載請註明本文出處:http://www.cnblogs.com/newton/p/6066020.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 今天去深圳溜達了一天,剛回來,看到首頁都是微軟大法好,看來離.NET的春天就差3個月了~~回到正題,這篇的教程講解下拉配置,詳情如下:... ...
  • 本文版權歸博客園和作者吳雙共同所有,轉載和爬蟲請註明原文地址:www.cnblogs.com/tdws 首先分享幾個振奮人心的新聞: 1.谷歌已經宣佈加入.NET基金會 2.微軟加入Linux基金會,繼續對Linux示好。換了CEO就是不一樣 3.微軟發佈VS For Mac! 第一步 下載dll ...
  • 從今天開始,正式進入Asp.net Core的開發,估計最近一段時間會經常寫博客了,記錄學些Asp.net Core中遇到的各種坑。 第一個問題:通過core編寫的webapi,預設返回的json會自動格式化為駝峰樣式,並沒有按照具體的類名來返回,如何讓其按照類名返回呢? 在Startup.cs全局 ...
  • 恢復內容開始 如何做到將客戶伺服器資料庫的備份,下載到本地的雲服務上? 在開發這個程式中中途也遇到了一下問題,下麵我將自己如何進解決的辦法寫出來供大家參考。 一.首先我需要進行描述一下問題: 1.比如有兩台伺服器A,B(雲伺服器) 將A中的伺服器中的資料庫的備份進行下載到B的雲服務中並保存。 2.當 ...
  • 感謝您的閱讀。喜歡的、有用的就請大哥大嫂們高抬貴手“推薦一下”吧!你的精神支持是博主強大的寫作動力以及轉載收藏動力。歡迎轉載! 版權聲明:本文原創發表於 【請點擊連接前往】 ,未經作者同意必須保留此段聲明!如有侵權請聯繫我刪帖處理! 我的博客:http://www.cnblogs.com/GJM6/ ...
  • 字元串轉組件名 字元串轉變數名 或 ...
  • EntityFramework 一對一關係映射有很多種,比如主鍵作為關聯,配置比較簡單,示例代碼: 上面代碼表示 Teacher 和 Student 一對一關係,Fluent API 配置如下: 測試代碼: 生成 SQL 代碼: 另一種 Fluent API 配置如下: 執行同樣測試代碼,生成 SQ ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...