阿里云oss使用

签名URL

浏览器打开的网页(我们的网站)想要支持用户传文件到服务端,一种办法就是通过http给到服务端,服务端在把文件给到单独的OSS服务。这个过程会经历一次中转效率低。文件大且多的时候,就得考虑应用服务的带宽负载,就无法直接使用上OSS的伸缩架构能力。

我们可以让网页直接把文件传给OSS服务,但是如果把OSS的账户密码给到网页使用是不安全的,这样阿里云官网提供了方案授权给第三方上传_对象存储(OSS)-阿里云帮助中心 (aliyun.com),我们要用一下其中的“签名URL”方式。

阿里云OSS的签名URL就支持get、put两种,get是下载文件,put是上传文件。

一、文件上传

服务端通过OSS SDK(比如Go语言的)生成一个上传文件用的“签名URL”,这样客户端可以凭借URL,不依赖OSS SDK直接上传文件。

这个URL在签名的时候设置了有效时长,而且一旦被使用过,URL就失效,确保了只能用一次。

签名是支持带可选参数的,如果服务端签URL的时候设置了content-type,比如 text/plain,那么客户端请求URL的时候其content-type也必须是text/plain。

// 如果要在前端使用带可选参数的签名URL,请确保在服务端生成该签名URL时设置的ContentType与在前端使用时设置的ContentType一致。
    options := []oss.Option{
        oss.Meta("myprop", "mypropval"),
        oss.ContentType("text/plain"),
    }
    
    signedURL, err = bucket.SignURL(objectName, oss.HTTPPut, 60, options...)
    if err != nil {
        HandleError(err)
    }
    fmt.Printf("Sign Url:%s\n", signedURL)

1、注意事项:content-type用不了multiple/form-data

用multiple/form-data的方式传文件是不行的,因为这个header头实际签名内容是不固定的。

比如

curl -k  --location --request PUT --X PUT 'https://xxxxxx/1.txt?Expires=1709709827&OSSAccessKeyId=xxxxx&Signature=xxxxx' \
--form 'file=@C:\Users\taiwu\Desktop\1.txt'

 请求后会得到报错信息,从报错中能看到服务端实际签名的原始字符串如下,这里面关于header的boundary=是动态的。

 <StringToSign>PUT

multipart/form-data; boundary=------------------------4452e35e5d6756d1
1709709827
/taiwu/1.txt</StringToSign>

2、注意事项:签名时没有content-type的情况

如果签名的时候没有设置content-type,那么客户端请求这个签名URL的时候也不能设置content-type,即不传content-type内容,传了也会报错。

这时候我们可以下面的curl模拟不到content-type的请求

curl -k -T 1.txt 'https://xxxxxx/1.txt?Expires=1709710727&OSSAccessKeyId=xxxxxx&Signature=xxxxxx'

3、文件是图片的情况

curl -k -T 111.jpg \
-H "Content-Type: image/jpeg" \
'https://xxxxxxxxxxxxxxxxxxxx'

我们要上传的如果是jpg图片,可以设置Content-Type为 image/jpeg, 用这个参数包含到签名过程中。

上面演示了如何用curl上传一个图片到指定的签名url地址。

这样上传的图片,当我们用浏览器访问的时候,服务端会返回文件类型是image/jpeg,浏览器能直接预览。

如果我们Content-Type不用,那么这样传的图片,后续用浏览器直接访问的时候,返回的内容类型是application/octet-stream,文件直接被下载了。


二、文件下载

签名URL是用get方式获取文件,对于下载用的url,签名的时候会有content-type,用的什么,那么下载时客户端(浏览器、curl等)调用的时候也必须使用同样的content-type,否则就会提示签名错误。

我们可以用curl -O 命令来下载文件,-O代表文件存的名称来自url,最后得到文件。

1、注意事项:请求content-type和签名时的必须一致

我们签名URL的时候,content-type不设置,那么用curl请求的时候,也不要带上content-type信息。比如用下面的curl就不带content-type,这样请求和签名URL的content-type都是空,是对的。

curl -k --request GET -O \
'https://xxxxxx/1.txt?Expires=1709717832&OSSAccessKeyId=xxxxxx&Signature=xxxxxx'

如果后台签名URL的时候用了特定的content-type,比如 octet-stream, 那么客户端请求的时候也必须带上这个头信息。比如我们用上面的curl方式请求,就会拿到错误信息,看签名内容,可以发现这么请求时签名里面没用content-type内容,但是服务端签名时字符串是有octet-stream的,这样自然对不上。

<?xml version="1.0" encoding="UTF-8"?>
<Error>
  <Code>SignatureDoesNotMatch</Code>
  <Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
  <RequestId>65E8284CE11F2694B961FA64</RequestId>
  <HostId>xxxxxxxxxxx</HostId>
  <OSSAccessKeyId>xxxxxxxxx</OSSAccessKeyId>
  <SignatureProvided>xxxxxxxx</SignatureProvided>
  <StringToSign>GET


1709718379
1.txt</StringToSign>
  <StringToSignBytes>xxxxxxx</StringToSignBytes>
</Error>

我们改为正确的请求指令,带上一直的content-type就可以了

curl -k --request GET -O \
'https://xxxxxx/1.txt?Expires=1709718379&OSSAccessKeyId=xxxxxx&Signature=xxxxxx' \
--header 'Content-Type:octet-stream'

三、OSS签名URL和VUE框架配合

1、上传

上传文件的时候,vue通过axios的put请求模式的content-type是 application/json;charset=UTF-8,所以我们提前生成的签名URL,在签名的时候提供application/json;charset=UTF-8这样能保证一致。数据落到OSS上面最终还是一个文件形式。

2、下载

下载文件的时候,vue通过axios的get请求,其默认的content-type是application/json;charset=UTF-8,所以我们生成下载的签名url时需要提供同样的content-type。

用curl模拟如下

curl -k -O \
--header 'Content-Type:application/json;charset=UTF-8' \
'https://xxxxxx/1.txt?Expires=1709719345&OSSAccessKeyId=xxxxx&Signature=xxxxxx'

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值