使用aws-sdk/client-s3删除DigitalOcean Spaces多文件遇501错误求助
DigitalOcean Spaces批量删除文件遇501 NotImplemented错误
问题详情
尝试从DigitalOcean Spaces中批量删除文件时持续报错,所有环境变量已正确配置。
当前代码
const { S3Client, DeleteObjectsCommand } = require("@aws-sdk/client-s3"); require("dotenv").config(); const s3 = new S3Client({ region: "sfo3", credentials: { accessKeyId: process.env.DO_SPACES_KEY, secretAccessKey: process.env.DO_SPACES_SECRET, }, endpoint: process.env.DO_SPACES_ENDPOINT, forcePathStyle: true, // Required for some S3-compatible services }); const deleteFile = async (keys) => { try { const keys = [ "1702039720121672541410-file_example_JPG_2500kB.jpg", "1702034408592871178538-file_example_PNG_2100kB.png", "1702034501011992084344-file_example_PNG_3MB.png", ]; const keysArray = []; keys.map((key) => keysArray.push({ Key: key })); console.log(keysArray); const deleteParams = { Bucket: process.env.DO_SPACES_NAME, Delete: { Objects: keysArray, // Quiet: false, }, }; const command = new DeleteObjectsCommand(deleteParams); const data = await s3.send(command).catch((err) => { console.log(err); }); console.log(data); return data; } catch (error) { console.error("Error deleting file:", error); throw error; } }; module.exports = deleteFile;
收到的错误信息
NotImplemented: UnknownError at throwDefaultError (C:\Users\username\Desktop\skrink-image\backend\node_modules\@smithy\smithy-client\dist-cjs\default-error-handler.js:8:22) { '$fault': 'client', '$metadata': { httpStatusCode: 501, requestId: 'tx0000016e999caa939aed5-00657a18e7-3c6e5030-sfo3a', extendedRequestId: undefined, cfId: undefined, attempts: 1, totalRetryDelay: 0 }, Code: 'NotImplemented', RequestId: 'tx0000016e999caa939aed5-00657a18e7-3c6e5030-sfo3a', HostId: '3c6e5030-sfo3a-sfo3-zg01' }
已尝试的操作
- 将
forcePathStyle设为false - 使用aws-sdk v2版本
以上两种方法均未解决问题。
package.json配置
{ "name": "backend", "version": "1.0.0", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "nodemon server.js", }, "author": "", "license": "ISC", "dependencies": { "@aws-sdk/client-s3": "^3.472.0", "@img/sharp-win32-x64": "^0.33.0", "aws-sdk": "^2.1515.0", "body-parser": "^1.20.2", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "fs-extra": "^11.2.0", "joi": "^17.11.0", "multer": "^1.4.5-lts.1", "mysql2": "^3.6.5", "node-cron": "^3.0.3", "nodemon": "^3.0.2", "sequelize": "^6.35.1", "sharp": "^0.33.0" }, "devDependencies": { "sequelize-cli": "^6.6.2" } }
解决方法
1. 修正Endpoint格式
DigitalOcean Spaces的标准Endpoint格式为https://<region>.digitaloceanspaces.com(比如sfo3区域对应https://sfo3.digitaloceanspaces.com),确保环境变量DO_SPACES_ENDPOINT没有包含Bucket名称,也不是未配置CNAME的自定义域名。
2. 调整forcePathStyle配置
DigitalOcean Spaces采用虚拟主机风格路径,需将forcePathStyle设为false,这是适配DO Spaces的关键配置。
3. 修复代码参数覆盖问题
你的deleteFile函数接收了keys参数,但内部又重新定义了同名变量覆盖传入值,建议移除内部的const keys = [...],直接使用传入的参数。
4. 修正后的完整代码
const { S3Client, DeleteObjectsCommand } = require("@aws-sdk/client-s3"); require("dotenv").config(); const s3 = new S3Client({ region: "sfo3", credentials: { accessKeyId: process.env.DO_SPACES_KEY, secretAccessKey: process.env.DO_SPACES_SECRET, }, endpoint: `https://${process.env.DO_SPACES_REGION || "sfo3"}.digitaloceanspaces.com`, forcePathStyle: false, }); const deleteFile = async (keys) => { try { const keysArray = keys.map(key => ({ Key: key })); const deleteParams = { Bucket: process.env.DO_SPACES_NAME, Delete: { Objects: keysArray, Quiet: false }, }; const command = new DeleteObjectsCommand(deleteParams); const data = await s3.send(command); console.log("删除成功:", data); return data; } catch (error) { console.error("删除失败:", error); throw error; } }; module.exports = deleteFile;
5. 验证权限
确保你的DO Spaces密钥拥有s3:DeleteObject权限,对应的IAM策略需包含:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:DeleteObject", "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*" } ] }
6. 先测试单个文件删除
如果批量删除仍报错,先使用DeleteObjectCommand测试单个文件删除,确认单个操作正常后再尝试批量,排查是否为批量接口的适配问题。
内容的提问来源于stack exchange,提问作者Shamoil khan
相关产品推荐
相关产品推荐

