- 开发者工具 IDE
- 沙盒环境
- 抖音云
- 产品介绍
- 快速开始
- 场景指南
- 操作指南
- 开发指南
- SDK参考
- 产品动态
- 产品计费
- 常见问题
- OpenAPI调试台
多端场景文件上传到对象存储的最佳实践
更新时间 2024-07-24 02:58:49
收藏
我的收藏介绍
业务场景中涉及到上传文件的场景,直接上传到服务端会受到带宽限制,大量用户并发上传会导致服务稳定性降低。
预签名URL中包含AK、有效期、资源、操作、签名等信息,任何使用该URL的人在有效期内都可以执行该URL对应的操作。这种方法称作预签名。
客户端首先从服务端获取需要上传的对象的预签名URL,然后客户端通过Http请求,将对象传至对象存储桶。
操作指引
获取对象存储 SDK访问密钥
在「对象存储-配置-密钥」生成对象存储SDK的访问密钥,标题栏为对象存储桶ID
预签名URL上传文件到对象存储
Golang代码示例
支持预签名的sdk详细使用说明文档如下
- •java-预签名
- •python-预签名
- •go-预签名
- •node.js-预签名
Go复制package main
import (
"encoding/json"
"fmt"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum"
"log"
"net/http"
)
func main() {
http.HandleFunc("/get_pre_sign_url", GetPreSignUrlHandler)
listenPort := ":8000"
if listenPort == "" {
log.Fatal("failed to load _FAAS_RUNTIME_PORT")
}
fmt.Println("http ListenAndServe ", listenPort)
log.Fatal(http.ListenAndServe(listenPort, nil))
}
var (
//填写从抖音云--对象存储--配置获取的AK和SK
accessKey = "xxxxxxxxxx"
secretKey = "xxxxxx"
// 如果部署在抖音云服务中,建议替换成内网域名
endpoint = "tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写从抖音云--对象存储获取的桶的ID
bucketName = "xxxxxxxxxx"
httpClient = &http.Client{}
)
func GetPreSignUrlHandler(w http.ResponseWriter, r *http.Request) {
// 初始化对象存储 client
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
if err != nil {
fmt.Fprint(w, "client init error")
return
}
objectName := r.URL.Query().Get("object_name")
// 调用Tos SDK 生成上传对象预签名
url, err := client.PreSignedURL(&tos.PreSignedURLInput{
HTTPMethod: enum.HttpMethodPut,
Bucket: bucketName,
Key: objectName,
})
if err != nil {
fmt.Fprint(w, "get pre sign url error")
return
}
data := make(map[string]string)
data[objectName] = url.SignedUrl
msg, err := json.Marshal(data)
if err != nil {
fmt.Fprint(w, "json marshal error")
return
}
w.Header().Set("content-type", "application/json")
w.Write(msg)
}
利用预签名 URL 在 Web 端进行上传示例
HTML复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input id="uploadFile" type="file">
<button onclick="upload()">上传</button>
<script>
function upload() {
const uploadFile = document.querySelector("#uploadFile");
const files = uploadFile.files;
let xhr = new XMLHttpRequest();
const fileReader = new FileReader();
fileReader.readAsArrayBuffer(files[0]);
fileReader.onloadend = function() {
// 转换为二进制流
const binaryData = fileReader.result;
// 从服务端获取预签名URL, 本文档中获取预签名URL的接口名称为/get_pre_sign_url
xhr.open("PUT", "XXX");
xhr.onload = function(response) {
console.log('reponse', response);
}
xhr.send(binaryData);
};
}
</script>
</body>
</html>
UGC 内容审核后文件权限从私有读转为公开读
文件上传到对象存储后,默认为私有读。UGC 内容建议审核后再修改文件权限为公开读,否则存在内容违规风险。
服务端Golang代码示例:修改文件权限为公开读
Go复制package main
import (
"context"
"fmt"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos"
"github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum"
"log"
"net/http"
)
func main() {
http.HandleFunc("/put_object_public_read", PutObjectPublicReadHandler)
listenPort := ":8000"
if listenPort == "" {
log.Fatal("failed to load _FAAS_RUNTIME_PORT")
}
fmt.Println("http ListenAndServe ", listenPort)
log.Fatal(http.ListenAndServe(listenPort, nil))
}
var (
//填写从抖音云--对象存储--配置获取的AK和SK
accessKey = "xxxxxxxxxx"
secretKey = "xxxxxx"
// 如果部署在抖音云服务中,建议替换成内网域名
endpoint = "tos-cn-beijing.volces.com"
region = "cn-beijing"
// 填写从抖音云--对象存储获取的桶的ID
bucketName = "xxxxxxxxxx"
httpClient = &http.Client{}
)
func PutObjectPublicReadHandler(w http.ResponseWriter, r *http.Request) {
//初始化请求对象存储的client
client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey)))
if err != nil {
fmt.Fprint(w, "client init error")
return
}
objectName := r.URL.Query().Get("object_name")
// 调用Tos SDK将对象访问权限变更公开读
acl := enum.ACLPublicRead
_, err = client.PutObjectACL(context.TODO(), &tos.PutObjectACLInput{Bucket: bucketName, Key: objectName, ACL: acl})
if err != nil {
fmt.Fprint(w, "PutObjectACL error")
return
}
w.Header().Set("content-type", "application/json")
w.Write([]byte("success"))
}
点击纠错