@@ -254,7 +254,7 @@ var getFileMd5 = function (body, callback) {
254254
255255function clone ( obj ) {
256256 return map ( obj , function ( v ) {
257- return typeof v === 'object' ? clone ( v ) : v ;
257+ return typeof v === 'object' && v !== null ? clone ( v ) : v ;
258258 } ) ;
259259}
260260
@@ -629,6 +629,13 @@ var canFileSlice = (function () {
629629 } ;
630630} ) ( ) ;
631631
632+ var isCIHost = function ( url ) {
633+ if ( url && url . split ( '?' ) [ 0 ] . match ( / ( .c i .| c i .| .c i ) / g) ) {
634+ return true ;
635+ }
636+ return false ;
637+ }
638+
632639var util = {
633640 noop : noop ,
634641 formatParams : formatParams ,
@@ -659,6 +666,7 @@ var util = {
659666 getAuth : getAuth ,
660667 compareVersion : compareVersion ,
661668 canFileSlice : canFileSlice ,
669+ isCIHost : isCIHost ,
662670} ;
663671
664672module . exports = util ;
@@ -2339,7 +2347,7 @@ base.init(COS, task);
23392347advance . init ( COS , task ) ;
23402348
23412349COS . getAuthorization = util . getAuth ;
2342- COS . version = '1.0.13 ' ;
2350+ COS . version = '1.1.0 ' ;
23432351
23442352module . exports = COS ;
23452353
@@ -8098,6 +8106,53 @@ function multipartAbort(params, callback) {
80988106 } ) ;
80998107}
81008108
8109+ /**
8110+ * 追加上传
8111+ * @param {Object } params 参数对象,必须
8112+ * @param {String } params.Bucket Bucket名称,必须
8113+ * @param {String } params.Region 地域名称,必须
8114+ * @param {String } params.Key object名称,必须
8115+ * @param {String } params.Body 上传文件的内容,只支持字符串
8116+ * @param {Number } params.Position 追加操作的起始点,单位为字节,必须
8117+ * @param {String } params.CacheControl RFC 2616 中定义的缓存策略,将作为 Object 元数据保存,非必须
8118+ * @param {String } params.ContentDisposition RFC 2616 中定义的文件名称,将作为 Object 元数据保存,非必须
8119+ * @param {String } params.ContentEncoding RFC 2616 中定义的编码格式,将作为 Object 元数据保存,非必须
8120+ * @param {String } params.ContentLength RFC 2616 中定义的 HTTP 请求内容长度(字节),必须
8121+ * @param {String } params.ContentType RFC 2616 中定义的内容类型(MIME),将作为 Object 元数据保存,非必须
8122+ * @param {String } params.Expect 当使用 Expect: 100-continue 时,在收到服务端确认后,才会发送请求内容,非必须
8123+ * @param {String } params.Expires RFC 2616 中定义的过期时间,将作为 Object 元数据保存,非必须
8124+ * @param {String } params.ACL 允许用户自定义文件权限,有效值:private | public-read,非必须
8125+ * @param {String } params.GrantRead 赋予被授权者读取对象的权限,格式:id="[OwnerUin]",可使用半角逗号(,)分隔多组被授权者,非必须
8126+ * @param {String } params.GrantReadAcp 赋予被授权者读取对象的访问控制列表(ACL)的权限,格式:id="[OwnerUin]",可使用半角逗号(,)分隔多组被授权者,非必须
8127+ * @param {String } params.GrantWriteAcp 赋予被授权者写入对象的访问控制列表(ACL)的权限,格式:id="[OwnerUin]",可使用半角逗号(,)分隔多组被授权者,非必须
8128+ * @param {String } params.GrantFullControl 赋予被授权者操作对象的所有权限,格式:id="[OwnerUin]",可使用半角逗号(,)分隔多组被授权者,非必须
8129+ * @param {String } params.StorageClass 设置对象的存储级别,枚举值:STANDARD、STANDARD_IA、ARCHIVE,默认值:STANDARD,非必须
8130+ * @param {String } params.x-cos-meta-* 允许用户自定义的头部信息,将作为对象的元数据保存。大小限制2KB,非必须
8131+ * @param {String } params.ContentSha1 RFC 3174 中定义的 160-bit 内容 SHA-1 算法校验,非必须
8132+ * @param {String } params.ServerSideEncryption 支持按照指定的加密算法进行服务端数据加密,格式 x-cos-server-side-encryption: "AES256",非必须
8133+ * @param {Function } callback 回调函数,必须
8134+ * @return {Object } err 请求失败的错误,如果请求成功,则为空。https://cloud.tencent.com/document/product/436/7730
8135+ * @return {Object } data 返回的数据
8136+ */
8137+ function appendObject ( params , callback ) {
8138+ submitRequest . call ( this , {
8139+ Action : 'name/cos:AppendObject' ,
8140+ method : 'POST' ,
8141+ Bucket : params . Bucket ,
8142+ Region : params . Region ,
8143+ action : 'append' ,
8144+ Key : params . Key ,
8145+ body : params . Body ,
8146+ qs : {
8147+ position : params . Position
8148+ } ,
8149+ headers : params . Headers ,
8150+ } , function ( err , data ) {
8151+ if ( err ) return callback ( err ) ;
8152+ callback ( null , data ) ;
8153+ } ) ;
8154+ }
8155+
81018156
81028157/**
81038158 * cos 内置请求
@@ -8119,6 +8174,8 @@ function multipartAbort(params, callback) {
81198174 headers : params . Headers ,
81208175 qs : params . Query ,
81218176 body : params . Body ,
8177+ Url : params . Url ,
8178+ rawBody : params . RawBody ,
81228179 } , function ( err , data ) {
81238180 if ( err ) return callback ( err ) ;
81248181 if ( data && data . body ) {
@@ -8616,7 +8673,7 @@ function _submitRequest(params, callback) {
86168673 var region = params . Region ;
86178674 var object = params . Key ;
86188675 var method = params . method || 'GET' ;
8619- var url = params . url ;
8676+ var url = params . url || params . Url ;
86208677 var body = params . body ;
86218678 var json = params . json ;
86228679 var rawBody = params . rawBody ;
@@ -8654,12 +8711,18 @@ function _submitRequest(params, callback) {
86548711 json : json ,
86558712 } ;
86568713
8714+ // 兼容ci接口
8715+ var token = 'x-cos-security-token' ;
8716+ if ( util . isCIHost ( url ) ) {
8717+ token = 'x-ci-security-token' ;
8718+ }
8719+
86578720 // 获取签名
86588721 opt . headers . Authorization = params . AuthData . Authorization ;
86598722 params . AuthData . Token && ( opt . headers [ 'token' ] = params . AuthData . Token ) ;
86608723 params . AuthData . ClientIP && ( opt . headers [ 'clientIP' ] = params . AuthData . ClientIP ) ;
86618724 params . AuthData . ClientUA && ( opt . headers [ 'clientUA' ] = params . AuthData . ClientUA ) ;
8662- params . AuthData . XCosSecurityToken && ( opt . headers [ 'x-cos-security- token' ] = params . AuthData . XCosSecurityToken ) ;
8725+ params . AuthData . XCosSecurityToken && ( opt . headers [ token ] = params . AuthData . XCosSecurityToken ) ;
86638726
86648727 // 清理 undefined 和 null 字段
86658728 opt . headers && ( opt . headers = util . clearKey ( opt . headers ) ) ;
@@ -8811,6 +8874,7 @@ var API_MAP = {
88118874 putObjectTagging : putObjectTagging ,
88128875 getObjectTagging : getObjectTagging ,
88138876 deleteObjectTagging : deleteObjectTagging ,
8877+ appendObject : appendObject ,
88148878
88158879 // 分块上传相关方法
88168880 uploadPartCopy : uploadPartCopy ,
@@ -8840,22 +8904,47 @@ module.exports.init = function (COS, task) {
88408904/* 18 */
88418905/***/ ( function ( module , exports ) {
88428906
8907+ function camSafeUrlEncode ( str ) {
8908+ return encodeURIComponent ( str )
8909+ . replace ( / ! / g, '%21' )
8910+ . replace ( / ' / g, '%27' )
8911+ . replace ( / \( / g, '%28' )
8912+ . replace ( / \) / g, '%29' )
8913+ . replace ( / \* / g, '%2A' ) ;
8914+ }
8915+
8916+ function getObjectKeys ( obj , forKey ) {
8917+ var list = [ ] ;
8918+ for ( var key in obj ) {
8919+ if ( obj . hasOwnProperty ( key ) ) {
8920+ list . push ( forKey ? camSafeUrlEncode ( key ) . toLowerCase ( ) : key ) ;
8921+ }
8922+ }
8923+ return list . sort ( function ( a , b ) {
8924+ a = a . toLowerCase ( ) ;
8925+ b = b . toLowerCase ( ) ;
8926+ return a === b ? 0 : ( a > b ? 1 : - 1 ) ;
8927+ } ) ;
8928+ } ;
8929+
88438930var obj2str = function ( obj ) {
8844- var i , key , val ;
8845- var list = [ ] ;
8846- var keyList = Object . keys ( obj ) ;
8847- for ( i = 0 ; i < keyList . length ; i ++ ) {
8848- key = keyList [ i ] ;
8849- val = obj [ key ] || '' ;
8850- list . push ( key + '=' + encodeURIComponent ( val ) ) ;
8851- }
8852- return list . join ( '&' ) ;
8931+ var i , key , val ;
8932+ var list = [ ] ;
8933+ var keyList = getObjectKeys ( obj ) ;
8934+ for ( i = 0 ; i < keyList . length ; i ++ ) {
8935+ key = keyList [ i ] ;
8936+ val = ( obj [ key ] === undefined || obj [ key ] === null ) ? '' : ( '' + obj [ key ] ) ;
8937+ key = camSafeUrlEncode ( key ) . toLowerCase ( ) ;
8938+ val = camSafeUrlEncode ( val ) || '' ;
8939+ list . push ( key + '=' + val )
8940+ }
8941+ return list . join ( '&' ) ;
88538942} ;
88548943
88558944var request = function ( params , callback ) {
88568945 var filePath = params . filePath ;
88578946 var headers = params . headers || { } ;
8858- var url = params . url ;
8947+ var url = params . url || params . Url ;
88598948 var method = params . method ;
88608949 var onProgress = params . onProgress ;
88618950 var requestTask ;
@@ -8894,6 +8983,7 @@ var request = function (params, callback) {
88948983 'Expires' ,
88958984 'x-cos-storage-class' ,
88968985 'x-cos-security-token' ,
8986+ 'x-ci-security-token' ,
88978987 ] ;
88988988 for ( var i in params . headers ) {
88998989 if ( params . headers . hasOwnProperty ( i ) && ( i . indexOf ( 'x-cos-meta-' ) > - 1 || headerKeys . indexOf ( i ) > - 1 ) ) {
0 commit comments