阿里云OSS跨域AJAX上传OPTIONS请求403问题的解决方案


阿里的文档是我见过最乱和最不好懂的!简直就不是帮助文档只是阿里码农的debug参考手册。

想解决问题耗尽你耐心和弄得眼花的搜索资料,我解决这个OSS跨域问题要在下面这3个文档中来回切换和1个论坛找帖子还有1个搜索引擎找资料,累觉不爱!

    文档首页 › 开放存储服务OSS › Getting-Started

    文档首页 › 开放存储服务OSS › 产品文档

    文档首页 › 开放存储服务OSS › API-Reference

    开发者论坛>开放存储服务OSS

    还有百度

终于在夜里凌晨1点搞定了阿里云OSS跨域AJAX上传的问题!!阿里论坛里的没一个贴实例,在这里我分享给大家:


用浏览器使用JS进行表单上传(PostObject)的时候主要经历了以下几个步骤: 

1. 发OPTIONS请求给OSS,如果这个时候OSS响应403,则上传终止 

2. 如果通过了OPTIONS请求,才会进行真正的PostObject

所以本文介绍从创建bucket开始到设置CORS,到通过浏览器以表单的形式直接上传到OSS。 

前提条件: 假设你已经有了OSS的ID和KEY,并且本地有一个HTTP Server


第一步: 

    Bucket属性 -> Cors设置 ->  

     Cors规则

      来源 :*

      来源可以设置多个,每行一个,每行最多能有一个"*"符号


      Method :GET POST PUT DELET EHEAD

      

      Allowed Header *

      Allowed Header可设置多个,每行一个,每行最多能有一个"*"符号

      

      Expose Header :[空]

      Expose Header可设置多个,每行一个,不能出现"*"符号

      

      缓存时间 :100 秒

      

第二步: 

      需要提交的字段有

      key、Content-Type、OSSAccessKeyId、policy、Signature、file(提交的key字段必须在file前面)

      提交地址

      action


      1.设置 key 上传文件的object名称(上传文件名)。 

        如果需要使用用户上传的文件名称作为object名,使用${filename}变量。

        例如:如果用户上传了文件b.jpg,而key域的值设置为/user/a/${filename},最终的object名为/user/a/b.jpg。

        如果文件名包含路径,则去除文件名中的路径,例如用户上传了文件a/b/c/b.jpg,则取文件名为b.jpg,

        若key域的值设置为/user/a/${filename},最终的object名为/user/a/b.jpg 

        相关帮助页:https://docs.aliyun.com/?spm=5176.383663.9.2.m3xUD6#/pub/oss/api-reference/object&PostObject


      2.设置 Content-Type 服务器REST请求头,例用文件后缀名(扩展名)获得文件的mime type类型

        //下面php方法你可以修改成你习惯的语言

        function get_mimetype($ext) {

            $mime_types = array (

                    'apk' => 'application/vnd.android.package-archive',

                    '3gp' => 'video/3gpp', 'ai' => 'application/postscript', 

                    'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 

                    'aiff' => 'audio/x-aiff', 'asc' => 'text/plain', 

                    'atom' => 'application/atom+xml', 'au' => 'audio/basic', 

                    'avi' => 'video/x-msvideo', 'bcpio' => 'application/x-bcpio', 

                    'bin' => 'application/octet-stream', 'bmp' => 'image/bmp', 

                    'cdf' => 'application/x-netcdf', 'cgm' => 'image/cgm', 

                    'class' => 'application/octet-stream', 

                    'cpio' => 'application/x-cpio', 

                    'cpt' => 'application/mac-compactpro', 

                    'csh' => 'application/x-csh', 'css' => 'text/css', 

                    'dcr' => 'application/x-director', 'dif' => 'video/x-dv', 

                    'dir' => 'application/x-director', 'djv' => 'image/vnd.djvu', 

                    'djvu' => 'image/vnd.djvu', 

                    'dll' => 'application/octet-stream', 

                    'dmg' => 'application/octet-stream', 

                    'dms' => 'application/octet-stream', 

                    'doc' => 'application/msword', 'dtd' => 'application/xml-dtd', 

                    'dv' => 'video/x-dv', 'dvi' => 'application/x-dvi', 

                    'dxr' => 'application/x-director', 

                    'eps' => 'application/postscript', 'etx' => 'text/x-setext', 

                    'exe' => 'application/octet-stream', 

                    'ez' => 'application/andrew-inset', 'flv' => 'video/x-flv', 

                    'gif' => 'image/gif', 'gram' => 'application/srgs', 

                    'grxml' => 'application/srgs+xml', 

                    'gtar' => 'application/x-gtar', 'gz' => 'application/x-gzip', 

                    'hdf' => 'application/x-hdf', 

                    'hqx' => 'application/mac-binhex40', 'htm' => 'text/html', 

                    'html' => 'text/html', 'ice' => 'x-conference/x-cooltalk', 

                    'ico' => 'image/x-icon', 'ics' => 'text/calendar', 

                    'ief' => 'image/ief', 'ifb' => 'text/calendar', 

                    'iges' => 'model/iges', 'igs' => 'model/iges', 

                    'jnlp' => 'application/x-java-jnlp-file', 'jp2' => 'image/jp2', 

                    'jpe' => 'image/jpeg', 'jpeg' => 'image/jpeg', 

                    'jpg' => 'image/jpeg', 'js' => 'application/x-javascript', 

                    'kar' => 'audio/midi', 'latex' => 'application/x-latex', 

                    'lha' => 'application/octet-stream', 

                    'lzh' => 'application/octet-stream', 

                    'm3u' => 'audio/x-mpegurl', 'm4a' => 'audio/mp4a-latm', 

                    'm4p' => 'audio/mp4a-latm', 'm4u' => 'video/vnd.mpegurl', 

                    'm4v' => 'video/x-m4v', 'mac' => 'image/x-macpaint', 

                    'man' => 'application/x-troff-man', 

                    'mathml' => 'application/mathml+xml', 

                    'me' => 'application/x-troff-me', 'mesh' => 'model/mesh', 

                    'mid' => 'audio/midi', 'midi' => 'audio/midi', 

                    'mif' => 'application/vnd.mif', 'mov' => 'video/quicktime', 

                    'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', 

                    'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 

                    'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 

                    'mpg' => 'video/mpeg', 'mpga' => 'audio/mpeg', 

                    'ms' => 'application/x-troff-ms', 'msh' => 'model/mesh', 

                    'mxu' => 'video/vnd.mpegurl', 'nc' => 'application/x-netcdf', 

                    'oda' => 'application/oda', 'ogg' => 'application/ogg', 

                    'ogv' => 'video/ogv', 'pbm' => 'image/x-portable-bitmap', 

                    'pct' => 'image/pict', 'pdb' => 'chemical/x-pdb', 

                    'pdf' => 'application/pdf', 

                    'pgm' => 'image/x-portable-graymap', 

                    'pgn' => 'application/x-chess-pgn', 'pic' => 'image/pict', 

                    'pict' => 'image/pict', 'png' => 'image/png', 

                    'pnm' => 'image/x-portable-anymap', 

                    'pnt' => 'image/x-macpaint', 'pntg' => 'image/x-macpaint', 

                    'ppm' => 'image/x-portable-pixmap', 

                    'ppt' => 'application/vnd.ms-powerpoint', 

                    'ps' => 'application/postscript', 'qt' => 'video/quicktime', 

                    'qti' => 'image/x-quicktime', 'qtif' => 'image/x-quicktime', 

                    'ra' => 'audio/x-pn-realaudio', 

                    'ram' => 'audio/x-pn-realaudio', 'ras' => 'image/x-cmu-raster', 

                    'rdf' => 'application/rdf+xml', 'rgb' => 'image/x-rgb', 

                    'rm' => 'application/vnd.rn-realmedia', 

                    'roff' => 'application/x-troff', 'rtf' => 'text/rtf', 

                    'rtx' => 'text/richtext', 'sgm' => 'text/sgml', 

                    'sgml' => 'text/sgml', 'sh' => 'application/x-sh', 

                    'shar' => 'application/x-shar', 'silo' => 'model/mesh', 

                    'sit' => 'application/x-stuffit', 

                    'skd' => 'application/x-koan', 'skm' => 'application/x-koan', 

                    'skp' => 'application/x-koan', 'skt' => 'application/x-koan', 

                    'smi' => 'application/smil', 'smil' => 'application/smil', 

                    'snd' => 'audio/basic', 'so' => 'application/octet-stream', 

                    'spl' => 'application/x-futuresplash', 

                    'src' => 'application/x-wais-source', 

                    'sv4cpio' => 'application/x-sv4cpio', 

                    'sv4crc' => 'application/x-sv4crc', 'svg' => 'image/svg+xml', 

                    'swf' => 'application/x-shockwave-flash', 

                    't' => 'application/x-troff', 'tar' => 'application/x-tar', 

                    'tcl' => 'application/x-tcl', 'tex' => 'application/x-tex', 

                    'texi' => 'application/x-texinfo', 

                    'texinfo' => 'application/x-texinfo', 'tif' => 'image/tiff', 

                    'tiff' => 'image/tiff', 'tr' => 'application/x-troff', 

                    'tsv' => 'text/tab-separated-values', 'txt' => 'text/plain', 

                    'ustar' => 'application/x-ustar', 

                    'vcd' => 'application/x-cdlink', 'vrml' => 'model/vrml', 

                    'vxml' => 'application/voicexml+xml', 'wav' => 'audio/x-wav', 

                    'wbmp' => 'image/vnd.wap.wbmp', 

                    'wbxml' => 'application/vnd.wap.wbxml', 'webm' => 'video/webm', 

                    'wml' => 'text/vnd.wap.wml', 

                    'wmlc' => 'application/vnd.wap.wmlc', 

                    'wmls' => 'text/vnd.wap.wmlscript', 

                    'wmlsc' => 'application/vnd.wap.wmlscriptc', 

                    'wmv' => 'video/x-ms-wmv', 'wrl' => 'model/vrml', 

                    'xbm' => 'image/x-xbitmap', 'xht' => 'application/xhtml+xml', 

                    'xhtml' => 'application/xhtml+xml', 

                    'xls' => 'application/vnd.ms-excel', 

                    'xml' => 'application/xml', 'xpm' => 'image/x-xpixmap', 

                    'xsl' => 'application/xml', 'xslt' => 'application/xslt+xml', 

                    'xul' => 'application/vnd.mozilla.xul+xml', 

                    'xwd' => 'image/x-xwindowdump', 'xyz' => 'chemical/x-xyz', 

                    'zip' => 'application/zip' );


              return (isset ( $mime_types[$ext] ) ?  $mime_types[$ext] : 'application/octet-stream');

          }


      3.填入 OSSAccessKeyId  Bucket 拥有者的Access Key Id。 


      

      4.设置 Policy 描述了匿名用户上传的一些限制.(Post policy中必须包含expiration和condtions。)

        policy规定了请求的表单域的合法性。不包含policy表单域的请求被认为是匿名请求,并且只能访问public-read-write的bucket。

        相关帮助页:https://docs.aliyun.com/?spm=5176.7189909.0.0.oom6oz#/pub/oss/api-reference/object&PostObject

        相关帮助页:https://docs.aliyun.com/?spm=5176.7189909.0.0.oom6oz#/pub/oss/sdk/java-sdk&object

        指定所允许上传的文件最大大小和最小大小,例如允许的文件大小为1到10字节: [“content-length-range”, 1, 10]


      5.设置 Signature 签名 根据Access Key Secret和policy计算的签名信息,OSS验证该签名信息从而验证该Post请求的合法性。

        Signature = base64_encode(hash_hmac("sha1", Policy , OSS_ACCESS_KEY, true)) 签名算法中用到上面的 Policy

        相关帮助文档:https://help.aliyun.com/knowledge_detail/5974545.html?spm=5176.7114037.1996646101.3.Fw2GcM&pos=2


      

      6.获得 action 提交地址 选定的文件会被上传到指定的Bucket,Bucket由表单中的URL来决定.

        相关帮助页:https://docs.aliyun.com/?spm=5176.383663.9.2.jSUv3m#/pub/oss/product-documentation/domain-region


      7.设置 file 文件或文本内容,必须是表单中的最后一个域(字段)。 OSS一次只能上传一个文件。


      备注:关于跨域的文档 https://docs.aliyun.com/?spm=5176.7189909.0.0.XnXwrm#/pub/oss/getting-started/bucket-attributes&cors

                                                   =5176.7189909.0.0.YkHckZ#/pub/oss/getting-started/bu


第三步:

      1. 第二步中1-6均可在服务端完成,并且能最好返回一个文件的下载地址供前端上传完毕后访问这个地址(也可以由前端去拼出这个下载地址)

      2. 前端完成第二步中7.file的选择再上传到6.action地址

      3. 上传后后处理下载地址搞定!!!


相关代码:


<form id="no_ajax_form" action="" method="post" enctype="multipart/form-data" >   <input  id="no_ajax_file" type="file" name="file"size="30" accept="audio/*,video/*,image/*" capture="camera" onchange="noajax(this)">   <input type="submit" value="非AJAX上传(可以改成AJAX)"> </form> <script> function noajax(obj){   var size = obj.files[0].size;        var filename = obj.files[0].name; //(必选参数)      //去服务器取签名      $.ajax({         url: " 你生成签名的服务器地址", //请求地址         method: 'GET',          dataType: "json",          data:{'filename':文件名字传过去,'}         })       //AJAX相关回调方法       .done(function( oss){          var noajaxform = $('#no_ajax_form');          noajaxform.attr('action',oss.action);          for(var k in oss.field){             noajaxform.prepend('<input name="'+k+'" value="'+oss.field[k]+'">');//你要把key这个input标签放到file前面……          }        });  } </script>

评论 ( 1 )
热度 ( 1 )