多吉云文档

https://docs.dogecloud.com/oss/sdk-introduction

基本代码

公共代码-鉴权

在文档里有这个介绍:

基于多吉云实现图片、文件上传下载 - 图1

dogeCLoudApi的代码如下:

  1. var axios = require('axios');
  2. var crypto = require('crypto');
  3. var querystring = require('querystring');
  4. /**
  5. * 调用多吉云API
  6. *
  7. * @param {string} apiPath 调用的 API 接口地址,包含 URL 请求参数 QueryString,例如:/console/vfetch/add.json?url=xxx&a=1&b=2
  8. * @param {object} data POST 的数据,对象,例如 {a: 1, b: 2},传递此参数表示不是 GET 请求而是 POST 请求
  9. * @param {boolean} jsonMode 数据 data 是否以 JSON 格式请求,默认为 false 则使用表单形式(a=1&b=2)
  10. * @param {function} callback 回调函数,兼容老版本调用代码,有两个参数,第一个参数表示错误,第二个参数是返回的数据
  11. *
  12. * @returns {Promise} 返回一个 Promise,在传递 callback 的情况下,可用 .then() 和 .catch() 处理返回的数据
  13. */
  14. function dogecloudApi(apiPath, data = {}, jsonMode = false, callback = null) {
  15. // 这里替换为你的多吉云永久 AccessKey 和 SecretKey,可在用户中心 - 密钥管理中查看
  16. // 请勿在客户端暴露 AccessKey 和 SecretKey,那样恶意用户将获得账号完全控制权
  17. const accessKey = '你的AccessKey';
  18. const secretKey = '你的SecretKey';
  19. const body = jsonMode ? JSON.stringify(data) : querystring.encode(data);
  20. const sign = crypto.createHmac('sha1', secretKey).update(Buffer.from(apiPath + "\n" + body, 'utf8')).digest('hex');
  21. const authorization = 'TOKEN ' + accessKey + ':' + sign;
  22. return new Promise(function(resolve, reject) {
  23. try {
  24. axios.request({
  25. url: 'https://api.dogecloud.com' + apiPath,
  26. method: 'POST',
  27. data: body,
  28. responseType: 'json',
  29. headers: {
  30. 'Content-Type': jsonMode ? 'application/json' : 'application/x-www-form-urlencoded',
  31. 'Authorization': authorization
  32. }
  33. })
  34. .then(function (response) {
  35. if (response.data.code !== 200) { // API 返回错误
  36. callback ? callback({Error: 'API Error: ' + response.data.msg}, null) : reject({errno: response.data.code, msg: 'API Error: ' + response.data.msg});
  37. return
  38. }
  39. callback ? callback(null, response.data.data) : resolve(response.data.data);
  40. })
  41. .catch(function (err) {
  42. callback ? callback(err, null) : reject(err);
  43. });
  44. } catch (error) {
  45. callback ? callback(error, null) : reject(err);
  46. }
  47. });
  48. }

引入 AWS JS SDK

基于多吉云实现图片、文件上传下载 - 图2

  1. npm install aws-sdk --save
  2. // 节省体积,只引入 S3 服务(推荐)
  3. const S3 = require('aws-sdk/clients/s3');
  4. // 或者:引入整个 AWS 包(不推荐)
  5. const AWS = require('aws-sdk'); // 请注意如果这样引入,下方代码中所有 “S3” 类名,需要改为 “AWS.S3”

初始化 AWS S3 SDK

先获取密钥:

  1. // 该 API 参考文档: https://docs.dogecloud.com/oss/api-tmp-token
  2. dogecloudApi('/auth/tmp_token.json', {
  3. channel: 'OSS_FULL',
  4. scopes: ['*']
  5. }, true, function(err, data) {
  6. if (err) { console.log(err.Error); return; }
  7. const credentials = data.Credentials;
  8. console.log(credentials);
  9. // 这里推荐使用 Redis 之类的缓存将获取到的临时密钥缓存下来,两小时内有效
  10. })

然后使用密钥,初始化S3实例:

  1. const s3 = new S3({ // 用服务端返回的信息初始化一个 S3 实例
  2. region: 'automatic',
  3. endpoint: data.Buckets[0].s3Endpoint, // 存储空间的 s3Endpoint 值,控制台存储空间 SDK 参数选项卡中也可以找到
  4. credentials: credentials,
  5. params: {
  6. Bucket: data.Buckets[0].s3Bucket // 存储空间的 s3Bucket 值,控制台存储空间 SDK 参数选项卡中也可以找到,
  7. // 这里先绑定好 s3Bucket,之后如果操作的是同一个存储空间,就不用再传递 Bucket 了
  8. }
  9. });

上传代码

  1. // 节省体积,只引入 S3 服务(推荐)
  2. import S3 from "aws-sdk/clients/s3";
  3. import {
  4. NODE_ENV,
  5. OSS_ACCESS_KEY_ID,
  6. OSS_ACCESS_KEY_SECRET,
  7. OSS_BUCKET,
  8. OSS_REGION,
  9. } from "@/config";
  10. import { myLog } from "./utils";
  11. var axios = require("axios");
  12. var crypto = require("crypto");
  13. var querystring = require("querystring");
  14. // 将顶层 await 移到一个异步函数中
  15. async function initializeS3() {
  16. try {
  17. // TODO 读取redis是否存在临时密钥
  18. // 获取临时密钥
  19. const data = await dogecloudApi(
  20. "/auth/tmp_token.json",
  21. {
  22. channel: "OSS_FULL",
  23. scopes: ["*"],
  24. },
  25. true,
  26. );
  27. myLog(data);
  28. // 初始化 S3 客户端
  29. const s3Client = new S3({
  30. region: "automatic",
  31. endpoint: process.env.R2_ENDPOINT,
  32. credentials: data?.Credentials,
  33. params: {
  34. Bucket: process.env.R2_BUCKET,
  35. },
  36. });
  37. s3Client;
  38. return s3Client;
  39. } catch (error) {
  40. console.error(error);
  41. }
  42. }
  43. // 这个方法用于获取 S3 客户端
  44. export default async function getDogeOSS() {
  45. try {
  46. return await initializeS3();
  47. } catch (error) {
  48. console.error(error);
  49. return null;
  50. }
  51. }
  52. /**
  53. /**
  54. * 调用多吉云API
  55. *
  56. * @param {string} apiPath 调用的 API 接口地址,包含 URL 请求参数 QueryString,例如:/console/vfetch/add.json?url=xxx&a=1&b=2
  57. * @param {object} data POST 的数据,对象,例如 {a: 1, b: 2},传递此参数表示不是 GET 请求而是 POST 请求
  58. * @param {boolean} jsonMode 数据 data 是否以 JSON 格式请求,默认为 false 则使用表单形式(a=1&b=2
  59. * @param {function} callback 废弃 回调函数,兼容老版本调用代码,有两个参数,第一个参数表示错误,第二个参数是返回的数据
  60. * @returns {Promise} 返回一个 Promise,在传递 callback 的情况下,可用 .then() 和 .catch() 处理返回的数据
  61. */
  62. function dogecloudApi(
  63. apiPath: string,
  64. data = {},
  65. jsonMode = false,
  66. callback = null,
  67. ) {
  68. // 这里替换为你的多吉云永久 AccessKey 和 SecretKey,可在用户中心 - 密钥管理中查看
  69. // 请勿在客户端暴露 AccessKey 和 SecretKey,那样恶意用户将获得账号完全控制权
  70. const accessKey = process.env.R2_ACCESSKEYID;
  71. const secretKey = process.env.R2_SECRET_ACCESSKEY;
  72. const body = jsonMode ? JSON.stringify(data) : querystring.encode(data);
  73. const sign = crypto
  74. .createHmac("sha1", secretKey)
  75. .update(Buffer.from(apiPath + "\n" + body, "utf8"))
  76. .digest("hex");
  77. const authorization = "TOKEN " + accessKey + ":" + sign;
  78. return new Promise(function (resolve, reject) {
  79. try {
  80. axios
  81. .request({
  82. url: "https://api.dogecloud.com" + apiPath,
  83. method: "POST",
  84. data: body,
  85. responseType: "json",
  86. headers: {
  87. "Content-Type": jsonMode
  88. ? "application/json"
  89. : "application/x-www-form-urlencoded",
  90. Authorization: authorization,
  91. },
  92. })
  93. .then(function (response: any) {
  94. if (response.data.code !== 200) {
  95. // API 返回错误
  96. callback
  97. ? callback({ Error: "API Error: " + response.data.msg }, null)
  98. : reject({
  99. errno: response.data.code,
  100. msg: "API Error: " + response.data.msg,
  101. });
  102. return;
  103. }
  104. callback
  105. ? callback(null, response.data.data)
  106. : resolve(response.data.data);
  107. })
  108. .catch(function (err: any) {
  109. callback ? callback(err, null) : reject(err);
  110. });
  111. } catch (error) {
  112. callback ? callback(error, null) : reject(error);
  113. }
  114. });
  115. }
  116. /**
  117. * 获取文件的 Content-Type
  118. */
  119. export function getContentType(fileName: string) {
  120. const ext = fileName.split(".").pop()?.toLowerCase();
  121. const mimeTypes = {
  122. jpg: "image/jpeg",
  123. jpeg: "image/jpeg",
  124. png: "image/png",
  125. gif: "image/gif",
  126. webp: "image/webp",
  127. pdf: "application/pdf",
  128. // 可以根据需要添加更多类型
  129. };
  130. return mimeTypes[ext || ""] || "application/octet-stream";
  131. }

踩坑

putObject需要回调函数

  1. await dogeOSS.putObject(params, function (err, data) {
  2. if (err) console.error("uploadImg", err, err.stack);
  3. else {
  4. console.log("uploadImg", data);
  5. }
  6. });
  7. 如果不传递回调函数,会导致根本没能成功上传

如何结合Url进行鉴权?

https://docs.dogecloud.com/cdn/manual-auth-key

cant find server acion

需要明示是哪一个接口

基于多吉云实现图片、文件上传下载 - 图3