@@ -13,7 +13,20 @@ export interface ISignature {
1313 signTime : string
1414}
1515
16- const generateSignature = ( options : ITcyunConfig , fileName : string ) : ISignature => {
16+ const cosSafeUrlEncode = ( str : string ) : string => {
17+ return encodeURIComponent ( str )
18+ . replace ( / ! / g, '%21' )
19+ . replace ( / ' / g, '%27' )
20+ . replace ( / \( / g, '%28' )
21+ . replace ( / \) / g, '%29' )
22+ . replace ( / \* / g, '%2A' )
23+ }
24+
25+ const generateContentType = ( fileName : string ) : string => {
26+ return mime . lookup ( fileName ) || 'application/octet-stream'
27+ }
28+
29+ const generateSignature = ( options : ITcyunConfig , fileName : string , contentType : string , contentLength : number ) : ISignature => {
1730 const secretId = options . secretId
1831 const secretKey = options . secretKey
1932 const appId = options . appId
@@ -37,7 +50,7 @@ const generateSignature = (options: ITcyunConfig, fileName: string): ISignature
3750 signTime = `${ today } ;${ tomorrow } `
3851 const signKey = crypto . createHmac ( 'sha1' , secretKey ) . update ( signTime ) . digest ( 'hex' )
3952 const endpoint = options . endpoint ? options . endpoint : `cos.${ options . area } .myqcloud.com`
40- const httpString = `put\n/${ options . path } ${ fileName } \n\nhost =${ options . bucket } .${ endpoint } \n`
53+ const httpString = `put\n/${ options . path } ${ fileName } \n\ncontent-length= ${ contentLength } &content-type= ${ cosSafeUrlEncode ( contentType ) } &host =${ options . bucket } .${ endpoint } \n`
4154 const sha1edHttpString = crypto . createHash ( 'sha1' ) . update ( httpString ) . digest ( 'hex' )
4255 const stringToSign = `sha1\n${ signTime } \n${ sha1edHttpString } \n`
4356 signature = crypto . createHmac ( 'sha1' , signKey ) . update ( stringToSign ) . digest ( 'hex' )
@@ -78,8 +91,9 @@ const postOptions = (options: ITcyunConfig, fileName: string, signature: ISignat
7891 url : `http://${ options . bucket } .${ endpoint } /${ encodeURI ( path ) } ${ encodeURIComponent ( fileName ) } ` ,
7992 headers : {
8093 Host : `${ options . bucket } .${ endpoint } ` ,
81- Authorization : `q-sign-algorithm=sha1&q-ak=${ options . secretId } &q-sign-time=${ signature . signTime } &q-key-time=${ signature . signTime } &q-header-list=host&q-url-param-list=&q-signature=${ signature . signature } ` ,
82- contentType : mime . lookup ( fileName ) ,
94+ Authorization : `q-sign-algorithm=sha1&q-ak=${ options . secretId } &q-sign-time=${ signature . signTime } &q-key-time=${ signature . signTime } &q-header-list=content-length;content-type;host&q-url-param-list=&q-signature=${ signature . signature } ` ,
95+ contentType : generateContentType ( fileName ) ,
96+ contentLength : image . byteLength ,
8397 'User-Agent' : `PicGo;${ version } ;null;null`
8498 } ,
8599 body : image ,
@@ -100,14 +114,14 @@ const handle = async (ctx: IPicGo): Promise<IPicGo | boolean> => {
100114 const useV4 = ! tcYunOptions . version || tcYunOptions . version === 'v4'
101115 for ( const img of imgList ) {
102116 if ( img . fileName && img . buffer ) {
103- const signature = generateSignature ( tcYunOptions , img . fileName )
104- if ( ! signature ) {
105- return false
106- }
107117 let image = img . buffer
108118 if ( ! image && img . base64Image ) {
109119 image = Buffer . from ( img . base64Image , 'base64' )
110120 }
121+ const signature = generateSignature ( tcYunOptions , img . fileName , generateContentType ( img . fileName ) , image . byteLength )
122+ if ( ! signature ) {
123+ return false
124+ }
111125 const options = postOptions ( tcYunOptions , img . fileName , signature , image , ctx . GUI_VERSION || ctx . VERSION )
112126 const res = await ctx . request ( options )
113127 . then ( ( res : any ) => res )
0 commit comments