OSS简介

Object Storage Service,简称 OSS,是阿里云提供的海量、安全、低成本、高可靠的云存储服务。

它具有与平台无关的RESTful API接口,能够提供99.999999999%的服务持久性。

使用场景:

  • 图片分享

  • 热点视频

优势:

  • 成本低(40G才6元,比ECS便宜太多)
  • 不会影响ECS带宽
  • 和服务器解耦

下面介绍一些基本功能:

  • 初始化

  • 创建存储空间

  • 上传文件

  • 跨域访问设置

  • 设置读写权限

OSS使用(NET SDK使用)

1.初始化

创建一个OssClient,就可以很方便的调用OSS的方法。

       const string accessKeyId = "xxxxxxxxx";
const string accessKeySecret = "xxxxxxxxxx";
const string endpoint = "oss-cn-beijing.aliyuncs.com"; //OSS对应的区域地址
private static OssClient ossClient = new OssClient(endpoint, accessKeyId, accessKeySecret);

2.创建存储空间

很简单,只需要调用OssClient.CreateBucket

   ossClient.CreateBucket("myBucket");		//新建一个Bucket

3.设置读写权限

调用OssClient.SetBucketAcl

   ossClient.SetBucketAcl("myBucket", CannedAccessControlList.PublicRead);	//设置为公共读

CannedAccessControlList有三个属性:Private(私有),PublicRead(公共读),PublicReadWrite(公共读写)

4.跨域访问设置

调用OssClient.SetBucketCors

   var req = new SetBucketCorsRequest("myBucket");
var rule = new CORSRule();
//指定允许跨域请求的来源
rule.AddAllowedOrigin("*");
//指定允许的跨域请求方法(GET/PUT/DELETE/POST/HEAD)
rule.AddAllowedMethod("POST");
//控制在OPTIONS预取指令中Access-Control-Request-Headers头中指定的header是否允许。
rule.AddAllowedHeader("*"); req.AddCORSRule(rule);
ossClient.SetBucketCors(req);

5.上传文件

调用OssClient.PutObject

   var result = ossClient.PutObject("myBucket", "111.mp4", @"d:\237badef-0f6d-4a8e-a634-a44c9704b6e6.mp4");
Console.WriteLine(result.ETag);

6.列出存储空间中的所有文件

调用ossClient.ListObjects

   var listObjectsRequest = new ListObjectsRequest("myBucket");
var result = ossClient.ListObjects(listObjectsRequest);
Console.WriteLine("List objects succeeded");
foreach (var summary in result.ObjectSummaries)
{
Console.WriteLine("File name:{0}", summary.Key);
}

以上步骤1到4,可以在OSS管理后端完成

WEB端直传

刚开始使用OSS的时候,是采用前端将文件流上传到Web服务器,然后通过Web服务器再上传到OSS

这种做法有三个缺点:

  • 第一:上传慢。先上传到应用服务器,再上传到OSS,网络传送多了一倍。如果数据直传到OSS,不走应用服务器,速度将大大提升,而且OSS是采用BGP带宽,能保证各地各运营商的速度。
  • 第二:扩展性不好。如果后续用户多了,应用服务器会成为瓶颈。
  • 第三:费用高。由于OSS上传流量是免费的。如果数据直传到OSS,不走应用服务器,那么将能省下几台应用服务器

如何操作?

1.通过JS控件直传

  • 采用plupload 直接提交表单数据(即PostObject)到OSS;
  • 在JS端,输入OSS的认证信息(不安全)
   var policyText = {
"expiration": "2020-01-01T12:00:00.000Z", //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了
"conditions": [
["content-length-range", 0, 1048576000] // 设置上传文件的大小限制
]
}; accessid= '6MKOqxGiGU4AUk44';
accesskey= 'ufu7nS8kS59awNihtjSonMETLI0KLy';
host = 'http://post-test.oss-cn-hangzhou.aliyuncs.com'; var policyBase64 = Base64.encode(JSON.stringify(policyText))
message = policyBase64
var bytes = Crypto.HMAC(Crypto.SHA1, message, accesskey, { asBytes: true }) ;
var signature = Crypto.util.bytesToBase64(bytes);
var uploader = new plupload.Uploader({
runtimes : 'html5,flash,silverlight,html4',
browse_button : 'selectfiles',
container: document.getElementById('container'),
flash_swf_url : 'lib/plupload-2.1.2/js/Moxie.swf',
silverlight_xap_url : 'lib/plupload-2.1.2/js/Moxie.xap',
url : host,
multipart_params: {
'Filename': '${filename}',
'key' : '${filename}',
'policy': policyBase64,
'OSSAccessKeyId': accessid,
'success_action_status' : '200', //让服务端返回200,不然,默认会返回204
'signature': signature,
}, init: {
PostInit: function() {
document.getElementById('ossfile').innerHTML = '';
document.getElementById('postfiles').onclick = function() {
uploader.start();
return false;
};
}, FilesAdded: function(up, files) {
plupload.each(files, function(file) {
document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ')<b></b>'
+'<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>'
+'</div>';
});
}, UploadProgress: function(up, file) {
var d = document.getElementById(file.id);
d.getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";

var prog = d.getElementsByTagName('div')[0];
var progBar = prog.getElementsByTagName('div')[0]
progBar.style.width= 2*file.percent+'px';
progBar.setAttribute('aria-valuenow', file.percent);
}, FileUploaded: function(up, file, info) {
//alert(info.status)
if (info.status >= 200 || info.status < 200)
{
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'success';
}
else
{
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response;
}
}, Error: function(up, err) {
document.getElementById('console').appendChild(document.createTextNode("\nError xml:" + err.response));
}
}
}); uploader.init();

具体可以下载OSS官网的 [例子]:https://help.aliyun.com/document_detail/31925.html?spm=a2c4g.11186623.6.629.AdgPho

2.通过服务端构建认证信息(安全,参看下一小节)

服务端构建认证信息

上一小节中,通过JS来上传文件,虽然可以上传,但是AppSecret会泄露,不安全。所以需要在服务端将认证信息构建出来,再给到前端

        public virtual ActionResult GetPostPolicy()
{
string host = "http://" + bucket + "."+ endpoint;
//第一步,构造policy
//var dir = "zhangsan/";//设置用户上传指定的前缀,必须以斜线结尾
var expiration = DateTime.Now.AddMinutes(100);
var policyConds = new PolicyConditions();
//policyConds.AddConditionItem(MatchMode.StartWith, PolicyConditions.CondKey, dir);//上传目录
policyConds.AddConditionItem(PolicyConditions.CondContentLengthRange, 1, 1048576000);//允许上传的文件大小限制
var postPolicy = ossClient.GeneratePostPolicy(expiration, policyConds);//给policyConds添加过期时间并json序列化(格式iso8601:"yyyy-MM-dd'T'HH:mm:ss.fff'Z'") //第二步 将policy 的json字符串进行base64编码
var base64Policy = Convert.ToBase64String(Encoding.UTF8.GetBytes(postPolicy)); //第三步,生成签名
var signature = ComputeSignature(accessKeySecret, base64Policy);//生成签名 //以下返回给前端
TimeSpan ts = expiration - new DateTime(1970, 1, 1, 0, 0, 0, 0);
var expire = Convert.ToInt64(ts.TotalSeconds); Dictionary<string, object> response = new Dictionary<string, object>();
response["accessid"] = accessKeyId;
response["host"] = host;
response["policy"] = base64Policy;
response["signature"] = signature;
response["expire"] = expire;
return ResponseSuccess(response); //返回json,可以自己修改(该方法是自己封装的)
} private static string ComputeSignature(string key, string data)
{
using (var algorithm = KeyedHashAlgorithm.Create("HmacSHA1".ToUpperInvariant()))
{
algorithm.Key = Encoding.UTF8.GetBytes(key.ToCharArray());
return Convert.ToBase64String(
algorithm.ComputeHash(Encoding.UTF8.GetBytes(data.ToCharArray())));
}
}

再结合刚才的前端,修改如下

<script type="text/javascript">
var accessid= '';
var host = 'http://muBucket.oss-cn-beijing.aliyuncs.com';
var policyBase64 = '';
var signature = '';
var uploadFileName=''; //文件名称
//获取随机字符串
function random_string(len) {
len = len || 32;
var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
var maxPos = chars.length;
var pwd = '';
for (i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
//获取文件后缀名
function get_suffix(filename) {
var pos = filename.lastIndexOf('.')
suffix = ''
if (pos != -1) {
suffix = filename.substring(pos)
}
return suffix;
}
//设置plupload属性
function set_upload_param(up, filename, ret)
{
var suffix='';
if (filename != '') {
suffix = get_suffix(filename)
}else{
return;
}
uploadFileName=random_string(20)+suffix;
new_multipart_params = {
'key' : uploadFileName,
'policy': policyBase64,
'OSSAccessKeyId': accessid,
'success_action_status' : '200', //让服务端返回200,不然,默认会返回204
'signature': signature,
};
up.setOption({
'url': host,
'multipart_params': new_multipart_params
});
up.start();
}
//初始化plupload控件
var uploader = new plupload.Uploader({
runtimes : 'html5,flash,silverlight,html4',
browse_button : 'selectfiles',
container: document.getElementById('container'),
flash_swf_url : 'lib/plupload-2.1.2/js/Moxie.swf',
silverlight_xap_url : 'lib/plupload-2.1.2/js/Moxie.xap',
multi_selection:false,
filters: {
mime_types : [
{ title : "Video files", extensions : "mp4,rmvb" }
],
max_file_size : '600000kb', //最大只能上传600M的文件
prevent_duplicates : true //不允许选取重复文件
},
url : host,
init: {
PostInit: function() {
document.getElementById('ossfile').innerHTML = '';
$.ajax({
type:'GET',
url:'GetPostPolicyURL', //获取认证信息的URL
success:function(res){
if(res.rspcode==="0000"){
accessid = res.accessid;
host = res.host;
policyBase64 =res.policy;
signature =res.signature; }else{
/* 弹出框提示错误 */
toastr.error(res.rspmsg);
}
}
})
}, FilesAdded: function(up, files) {
plupload.each(files, function(file) {
set_upload_param(up, file.name, true);
document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ')<b></b>'
+'<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>'
+'</div>';
});
}, BeforeUpload: function(up, file) { }, UploadProgress: function(up, file) {
var d = document.getElementById(file.id);
d.getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>"; var prog = d.getElementsByTagName('div')[0];
var progBar = prog.getElementsByTagName('div')[0]
progBar.style.width= 2*file.percent+'px';
progBar.setAttribute('aria-valuenow', file.percent);
}, FileUploaded: function(up, file, info) {
if (info.status >= 200 || info.status < 200)
{
vm.formModel.VideoPath=uploadFileName; //将文件名记录下来,用于保存
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'success';
}
else
{
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response;
}
}, Error: function(up, err) {
document.getElementById('console').appendChild(document.createTextNode("\nError xml:" + err.response));
}
}
}); uploader.init(); </script>

参考文章:

[OSS官网文档]:https://help.aliyun.com/document_detail/31817.html?spm=a2c4g.11186623.6.539.PK7qiJ

最新文章

  1. HTML5 语义元素(二)文本内容
  2. SQLite学习笔记(十二)&amp;&amp;虚拟机指令
  3. [软件推荐]Windows文件夹多标签工具Clover
  4. S3C2440 LCD驱动(FrameBuffer)实例开发&lt;一&gt;(转)
  5. swift-网络请求
  6. TCP协议承载的DNS报文,DNS报文首部前多出两个字节的DNS报文长度字段,是何意义?
  7. myEclipse修改deploy location
  8. JS中的函数传参
  9. Eclipse Jetty插件安装
  10. Qt 如何使用 lambda 表达式连接信号和槽?
  11. JAVA集合类——难得的总结
  12. missing requires of libmysqlclient.so.18()(64bit)
  13. Keil生成汇编文件、bin文件
  14. Qt的Radio Button(单选按钮)
  15. Python之路PythonNet,第四篇,网络4
  16. 阿里云Redis外网转发访问
  17. Delphi中ClientDataSet的用法小结
  18. 下载任意版本的Chromium
  19. 什么是&quot;抓包&quot;?怎样&quot;抓包&quot;?
  20. JZOJ6096 森林

热门文章

  1. PAT(B) 1033 旧键盘打字(C) 字符
  2. AJAX调用案例随笔(个人观看使用)
  3. Code First 下自动更新数据库结构(Automatic Migrations)
  4. MVC-07数据库
  5. 4_PHP流程控制语句_2_循环结构
  6. iOS开发-NSString去掉所有换行及空格
  7. ios获取数组中的最大值
  8. win10 下的anaconda3 安装(2019.06.04最新)
  9. 流程控制-switch
  10. Android笔记(二十七) Android中的动态广播和静态广播