鸿蒙环境服务端签名直传文件到OSS
本文介绍如何在鸿蒙环境下将文件上传到OSS。
背景信息
鸿蒙环境是当下比较流行的操作环境,与服务端签名直传的原理类似,鸿蒙环境上传文件到OSS是利用OSS提供的PutObject接口来实现文件上传到OSS。关于PutObject的详细介绍,请参见PutObject。
说明
本文只展示关于鸿蒙环境下服务端签名直传的关键代码片段,如果您需要了解更多详细信息,请下载完整示例:oss-js-sdk-harmony-demo.zip
步骤一:获取签名URL
为了您的数据安全,建议使用签名方式上传文件。OSS提供服务端签名和客户端签名两种签名方式, 这里以服务端签名为例:
说明
使用代码前,您需要先安装OSS SDK。更多信息,请参见安装。
使用服务端获取签名时,您需要先搭建一个签名服务,然后由客户端调用签名服务生成签名URL,具体步骤如下:
-
搭建服务端接口。
const express = require("express"); const mime = require("mime"); const OSS = require("ali-oss"); const app = express(); const port = 3000; // 监听端口 app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.post("/get_sign_url", async (req, res) => { const { fileName, method, headers = {}, queries = {}, additionalHeaders = [], } = req.body; // 从body中解析出数据 const client = new OSS({ region: "yourRegion", accessKeyId: "yourAccessKey", accessKeySecret: "yourAccessKeySecret", stsToken: "yourSTSToken", bucket: "yourBucket", authorizationV4: true, }); const reqHeaders = { ...headers, }; // 处理一下content-type if (fileName && method === "PUT") { const fileNameSplit = fileName.split("."); reqHeaders["content-type"] = mime.getType( fileNameSplit.length > 1 ? fileNameSplit[fileNameSplit.length - 1] : "" ); } // 生成V4签名URL const url = await client.signatureUrlV4( method, 300, { headers: reqHeaders, queries, }, fileName, additionalHeaders ); res.json({ url, contentType: reqHeaders["content-type"], }); }); app.listen(port, () => { console.log(`Example app listening on port ${port}`); });
-
在客户端获取签名URL。
import { http } from '@kit.NetworkKit'; import fs from '@ohos.file.fs'; import { request } from './request'; const serverUrl = 'http://x.x.x.x:3000/get_sign_url'; // 获取签名URL的服务器URL /** * getSignUrl返回数据 */ export interface ISignUrlResult { /** 签名URL */ url: string; /** content-type */ contentType?: string; } /** * 获取签名URL * @param fileName 文件名称 * @param req 用于生成V4签名URL的请求信息 * @param req.method 请求方式 * @param [req.headers] 请求头 * @param [req.queries] 请求查询参数 * @param [req.additionalHeaders] 加签的请求头 */ const getSignUrl = async (fileName: string, req: { method: 'GET' | 'POST' | 'PUT'; headers?: Record<string, string | number>; queries?: Record<string, string>; additionalHeaders?: string[]; }): Promise<ISignUrlResult> => { console.info('in getSignUrl'); try { const response = await request(serverUrl, { method: http.RequestMethod.POST, header: { 'Content-Type': 'application/json' }, extraData: { fileName, method: req.method, headers: req.headers, queries: req.queries, additionalHeaders: req.additionalHeaders }, expectDataType: http.HttpDataType.OBJECT }, 200); const result = response.result as ISignUrlResult; console.info('success getSignUrl'); return result; } catch (err) { console.info('getSignUrl request error: ' + JSON.stringify(err)); throw err; } };
步骤二:使用鸿蒙系统上传
使用签名URL上传文件,示例代码如下:
import { http } from '@kit.NetworkKit';
import fs from '@ohos.file.fs';
import { request } from './request';
const putObject = async (fileUri: string): Promise<void> => {
console.info('in putObject');
const fileInfo = await fs.open(fileUri, fs.OpenMode.READ_ONLY);
const fileStat = await fs.stat(fileInfo.fd);
let signUrlResult: ISignUrlResult;
console.info('file name: ', fileInfo.name);
try {
// 获取PutObject的签名URL
signUrlResult = await getSignUrl(fileInfo.name, {
method: 'PUT',
headers: {
'Content-Length': fileStat.size
},
additionalHeaders: ['Content-Length']
});
} catch (e) {
await fs.close(fileInfo.fd);
throw e;
}
const data = new ArrayBuffer(fileStat.size);
await fs.read(fileInfo.fd, data);
await fs.close(fileInfo.fd);
try {
// 使用PutObject方法上传文件
await request(signUrlResult.url, {
method: http.RequestMethod.PUT,
header: {
'Content-Length': fileStat.size,
'Content-Type': signUrlResult.contentType
},
extraData: data
}, 200);
console.info('success putObject');
} catch (err) {
console.info('putObject request error: ' + JSON.stringify(err));
throw err;
}
};
默认情况下,OSS存储空间中文件的读写权限是私有,仅文件拥有者具有访问文件的权限。但是,文件拥有者可以通过创建签名URL的方式与第三方用户分享文件,签名URL使用安全凭证的方式授权第三方用户在指定时间内下载或者预览文件。
注意事项
-
生成签名URL过程中,SDK利用本地存储的密钥信息,根据特定算法计算出签名(signature),然后将其附加到URL上,以确保URL的有效性和安全性。这一系列计算和构造URL的操作都是在客户端完成,不涉及网络请求到服务端。因此,生成签名URL时不需要授予调用者特定权限。但是,为避免第三方用户无法对签名URL授权的资源执行相关操作,需要确保调用生成签名URL接口的身份主体被授予对应的权限。
例如,通过签名URL下载或预览文件时,需要授予
oss:GetObject
权限。 -
如需确保通过文件URL访问文件时是预览行为,您需要绑定自定义域名并添加CNAME记录。详情请参见绑定自定义域名至Bucket默认域名。
-
获取私有文件URL时涉及设置URL的有效时长。超出文件URL设置的有效时长后,通过文件URL访问时会提示签名URL已过期,导致无法正常访问文件。如果您希望继续访问该文件,需要选择以下任意方式重新获取签名URL。
获取单个文件的URL
私有文件
公共读文件
如果文件读写权限ACL为私有,则必须进行签名操作。私有文件URL的格式为https://BucketName.Endpoint/Object?签名参数
。您可以通过以下任意方法获取文件URL并设置URL的有效时长。
重要
文件URL的有效时长因账号类型存在差异。例如,阿里云账号通过OSS控制台可设置的文件URL有效时长最大为32400秒(9小时),RAM用户以及STS用户可设置的文件URL有效时长最大为3600秒(1小时)。如需获取更长时效的文件URL,请使用命令行工具ossutil、图形化管理工具ossbrowser或阿里云SDK。更多信息,请参见私有文件签名URL有效时长。
使用OSS控制台
使用图形化管理工具ossbrowser
使用阿里云SDK
使用命令行工具ossutil
您可以通过OSS控制台获取单个文件的URL。
-
登录OSS管理控制台。
-
单击Bucket列表,然后单击目标Bucket名称。
-
在左侧导航栏,选择文件管理 > 文件列表。
-
获取文件URL。
-
单击目标文件名称。
-
在详情面板配置以下参数,然后单击复制文件 URL。
参数
说明
过期时间
当目标文件为私有文件时,需设置文件URL的有效时间。
取值范围:60~32400
单位:秒
如果您希望设置更长过期时间的文件URL,您可以使用ossbrowser、sdk、ossutil等工具。
自有域名
如需确保第三方访问图片或网页文件时是预览行为,请使用Bucket绑定的自定义域名生成文件URL。
仅当Bucket绑定自定义域名后可配置此项。更多信息,请参见绑定自定义域名。
使用HTTPS
默认使用HTTPS协议生成文件URL。如需使用HTTP协议生成文件URL,请关闭使用HTTPS开关。
-
获取多个文件的URL
仅OSS控制台支持批量获取多个文件的URL。
-
选中目标文件,然后单击下方的导出URL列表。
-
在导出URL列表面板,配置以下参数:
参数
说明
使用HTTPS
默认使用HTTPS协议生成文件URL。如需使用HTTP协议生成文件URL,请关闭使用HTTPS开关。
过期时间
当目标文件为私有文件时,需设置文件URL的有效时间。
取值范围:60~32400
单位:秒
若您希望获取更长时效的文件URL,建议使用命令行工具ossutil或图形化工具ossbrowser。
自有域名
如需确保第三方访问图片或网页文件时是预览行为,请使用Bucket绑定的自定义域名生成文件URL。
仅当Bucket绑定自定义域名后可配置此项。更多信息,请参见绑定自定义域名。
传输加速域名
若第三方涉及跨国或跨洋等超远距离文件访问场景时,建议使用传输加速域名生成文件URL。
仅当Bucket开启传输加速后可配置此项。更多信息,请参见开启传输加速。
-
单击确定,然后将URL列表文件保存到本地。
说明
如果您希望通过命令行管理工具ossutil、阿里云SDK批量获取多个文件的URL时:
-
通过GetBucket (ListObjects)接口获取所有Object的名称。
-
循环调用获取单个文件的URL方法。具体操作,请参见获取单个文件的URL。