开发者社区> 问答> 正文

设置跨域资源共享CORS并使用JS表单PostObject直接上传到OSS

CORS是什么?其实OSS一直官方文档也没有说清楚。PostObject怎么用官方也一直没有代码示例。

发现有两篇文章解释了下:
一篇是英文的,来自于:
http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
一篇是中文的,来自于:
利用跨域资源共享(CORS)实现ajax跨域调用
http://blogread.cn/it/article/3542?f=wb


如果用浏览器使用JS进行表单上传(PostObject)的时候会发生什么事情?
主要经历了以下几个步骤:
1. 发OPTIONS请求给OSS,如果这个时候OSS响应403,则上传终止
2. 如果通过了OPTIONS请求,才会进行真正的PostObject
所以本文介绍从创建bucket开始到设置CORS,到通过浏览器以表单的形式直接上传到OSS。
前提条件:
假设你已经有了OSS的ID和KEY,并且本地有一个HTTP Server
第一步:
下载osscmd,需要python的环境,osscmd下载及使用具体见:
http://docs.aliyun.com/?spm=5176.383663.9.4.DrXKYw#/oss/sdk/sdk-download&python


第二步:
创建bucket,假设你已经会使用了osscmd,并且已经使用python osscmd config --host=oss-cn-hangzhou.aliyuncs.com --id=xxx --key=xxx 配置好你的HOST,ID和KEY。这里xxx需要替换成OSS实际的ID和KEY,可以从控制台的右上角的钥匙图标获取。
本文以cors-test bucket为例子,你需要替换成一个不重名的bucket
已经执行config的,请使用 python osscmd cb cors-test 创建bucket
如果没有执行config,请使用python osscmd cb cors-test --host=oss-cn-hangzhou.aliyuncs.com --id=xxx --key=xxx
也可通过官方的控制台创建bucket。
记下创建的bucket和host。
如果是控制台创建,青岛的bucket host为oss-cn-qingdao.aliyuncs.com,杭州的bucket host为oss-cn-hangzhou.aliyuncs.com


第三步:
下载代码,
并将ID,KEY,BUCKET,HOST换成自己实际使用的ID,KEY,  BUCKET和HOST使用第二步创建的bucket和使用的host。
放入到HTTP Server的服务目录里,例如我的放在/var/www/html/test/postobject
然后通过浏览器上传http://10.101.166.53/test/post_object_to_oss.html
请注意,
如图所示,在我的代码中我分别将BUCKET,HOST替换成cors-test, 和oss-cn-hangzhou.aliyuncs.com。ID和KEY都替换成自己的。



这个时候如果直接上传会发现失败,查看HTTP头部如图所示,会发现403。这是因为新创建的bucket没有进行任何CORS相关的测试。

使用chrome浏览器自带的开发者工具查看http头的方法
1.在网页任意地方右击 选择审查元素或者按下 shift+ctrl+c, 打开chrome自带的调试工具;
2. 选择network标签, 刷新网页(在打开调试工具的情况下刷新);
3.刷新后在左边找到该网页url,点击 后 右边选择headers,就可以看到当前网页的http头了;

需要注意的是:
浏览器发送了 Request Method:OPTIONS 并且还发送了如下几个Header,

  • Access-Control-Request-Headers:content-type
  • Access-Control-Request-Method:POST
  • Host:cors-test.oss-cn-hangzhou.aliyuncs.com
  • Origin:http://10.101.166.53


使用getcors命令的时候发现,没有设置CORS
$osscmd getcors oss://cors-test


<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>NoSuchCORSConfiguration</Code>
  <Message>The CORS Configuration does not exist.</Message>
  <BucketName>cors-test</BucketName>
  <RequestId>54DB99D844F4D8594D991B50</RequestId>
  <HostId>cors-test.oss-cn-hangzhou.aliyuncs.com</HostId>
</Error>
Error Status:
404
getcors Failed!


第四步:
根据第三步浏览器中发送的Header,设置CORS
例如设置成:
<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>http://10.101.166.53</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
保存在cors.xml


为什么要这么设置?
因为第三步浏览器发送了 Origin:http://10.101.166.53,所以需要设置<AllowedOrigin>http://10.101.166.53</AllowedOrigin>
因为浏览器发送 Access-Control-Request-Method:POST,所以需要设置<AllowedMethod>POST</AllowedMethod>,
因为浏览器发送 Access-Control-Request-Headers:content-type,所以需要设置<AllowedHeader>*</AllowedHeader>


如何设置?
osscmd putcors oss://cors-test cors.xml
也可以通过控制台去设置,这里不多说


如何检查设置成功?
如果运行
$osscmd getcors oss://cors-test
出现如下的响应则表示成功
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>http://10.101.166.53</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>


第五步:
重新使用浏览器上传,发现此时已经成功
如图
查看HTTP头部会发现一次OPTIONS请求,一次PostObject请求



由于代码中object的name为
var key = "events/" + (new Date).getTime() + '-' + file.name;
所以用osscmd可以查看bucket中已经上传的object
$osscmd ls oss://cors-test/events/
prefix list is:
object list is:
2015-02-12 01:05:01 48.71KB Standard oss://cors-test/events/1423674299912-Snip20150204_4.png


有几点要说明下:
1. JS的代码实际是来自于互联网,已经忘记了出处,如果有侵犯你的利益,请联系,我会删除掉。
2. 这只是一个Sample,ID和KEY是直接写在代码中的,肯定不能直接用于生产,需要做些安全处理。
PostObject其实是一个很有用的功能,尤其是对网站用户。比如找工作的网站可以让网站的用户将简历上传到OSS,而无需经过网站的服务器,大大减少对网站服务器的流量压力。





展开
收起
wood23 2015-02-12 08:11:09 42861 0
5 条回答
写回答
取消 提交回答
  • 2017-05-24 07:03:51
    赞同 展开评论 打赏
  • 如何在使用STS情况下,通过js异步提交上传文件到OSS
    STS临时口令有后台生成,然后如何使用获取的临时口令异步上传文件, 各位大神!
    2017-05-23 15:36:58
    赞同 展开评论 打赏
  • 请问一个问题:使用上述方法可以上传文件,甚至可以利用multipartupload来上传文件,但是在completeMultipartUpload的时候,总是报:

    已阻止跨源请求:同源策略禁止读取位于 http:___mybucket.oss-cn-hongkong.aliyuncs.com/ 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。

    难道我的CORS可以part上传,但是不可以完成part上传?代码如下:

    var xmlDoc = createXML();
    var content = new XMLSerializer().serializeToString(xmlDoc);
    var size = strLen(content);

    var xhr = createXmlHttpRequest();
    xhr.addEventListener("load", uploadStatusUpdate, false);
    xhr.open('POST', 'http://mybucket.oss-cn-hongkong.aliyuncs.com', true);
    xhr.setRequestHeader('PUT','/' + file + '?uploadId=' + uploadId);
    xhr.setRequestHeader('Content-Length',size);
    xhr.setRequestHeader('OSSAccessKeyId', 'myAccessKeyId');
    xhr.setRequestHeader('policy',policyBase64_2);
    xhr.setRequestHeader('Authorization',signature);
    xhr.setRequestHeader('Content-Type',"text/xml");
                
    xhr.send(content);

    提前谢谢!
    2015-06-15 17:27:54
    赞同 展开评论 打赏
  • oos postobject表单上传后,如何获取包含md5的etag?
    2015-03-11 16:10:51
    赞同 展开评论 打赏
  • Re设置CORS并使用JS表单PostObject直接上传到OSS
    PHP的相关上传示例
    http://bbs.aliyun.com/read/227466.html?spm=5176.7189909.0.0.k2DnwA
    2015-02-12 08:28:03
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
JavaScript函数 立即下载
Delivering Javascript to World 立即下载
编程语言如何演化-以JS的private为例 立即下载