Skip to content

Commit 3a4e4fa

Browse files
committed
fix 02
1 parent 6619428 commit 3a4e4fa

File tree

1 file changed

+45
-13
lines changed
  • packages/filesystem/s3

1 file changed

+45
-13
lines changed

packages/filesystem/s3/s3.ts

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ export default class S3FileSystem implements FileSystem {
5858
};
5959

6060
if (endpoint) {
61+
// AWS SDK v3 要求 endpoint 是完整 URL(带 https://)。缺少协议会导致 InvalidEndpoint 或连接失败。
62+
// 自动补全协议(常见兼容做法)
63+
let fixedEndpoint = `${endpoint}`.trim();
64+
if (!fixedEndpoint.startsWith("http://") && !fixedEndpoint.startsWith("https://")) {
65+
fixedEndpoint = `https://${fixedEndpoint}`;
66+
}
6167
config.endpoint = endpoint;
6268
// 自动检测:如果 endpoint 包含 amazonaws.com,设为 false。
6369
if (endpoint.includes("amazonaws.com")) config.forcePathStyle = false;
@@ -78,18 +84,27 @@ export default class S3FileSystem implements FileSystem {
7884
});
7985
await this.client.send(command);
8086
} catch (error: any) {
87+
if (error.name === "NotFound") {
88+
throw new Error("NotFound"); // Bucket 不存在
89+
}
8190
if (
8291
error.name === "InvalidAccessKeyId" ||
8392
error.name === "SignatureDoesNotMatch" ||
8493
error.name === "InvalidClientTokenId"
8594
) {
86-
throw new WarpTokenError(error);
95+
throw new WarpTokenError(error); // AccessKey 或 SecretKey 无效
96+
}
97+
if (error.name === "AccessDenied") {
98+
throw new Error("Access Denied"); // 无权限访问该 Bucket(Access Denied)
99+
}
100+
if (error.name === "PermanentRedirect") {
101+
throw new Error("Access Denied"); // Region 设置错误,请检查 region 是否匹配 Bucket 所在区域
87102
}
88103
if (error.name === "NoSuchBucket") {
89104
throw new Error(`Bucket not found: ${this.bucket}`);
90105
}
91106
if (error.message?.includes("getaddrinfo") || error.message?.includes("fetch failed")) {
92-
throw new Error("Network connection failed. Please check your internet connection.");
107+
throw new Error("Network connection failed. Please check your internet connection."); // 网络连接失败,请检查 endpoint 或网络
93108
}
94109
throw error;
95110
}
@@ -115,10 +130,11 @@ export default class S3FileSystem implements FileSystem {
115130
const fs = new S3FileSystem(
116131
this.bucket,
117132
this.region,
118-
"", // These won't be used since we're reusing the client
133+
"", // 占位: These won't be used since we're reusing the client
119134
"",
120135
undefined,
121-
newBasePath
136+
newBasePath,
137+
true // forcePathStyle 同父
122138
);
123139
// openDir 又 new 一个 S3FileSystem,但传了空字符串的 AK/SK,导致逻辑不清晰。
124140
// 复用原有 client,只修改 basePath。
@@ -187,25 +203,37 @@ export default class S3FileSystem implements FileSystem {
187203
Prefix: prefix,
188204
Delimiter: "/",
189205
ContinuationToken: continuationToken,
206+
MaxKeys: 1000, // ← 每次最多 1000,防滥用
190207
});
191208

192209
const response = await this.client.send(command);
193210

211+
// 处理 CommonPrefixes(子目录)
212+
// if (response.CommonPrefixes) {
213+
// for (const prefix of response.CommonPrefixes) {
214+
// if (prefix.Prefix && prefix.Prefix !== this.basePath) {
215+
// }
216+
// }
217+
// }
218+
219+
// 处理 Contents(文件)
194220
if (response.Contents) {
195-
for (const object of response.Contents) {
196-
if (!object.Key) continue;
221+
for (const obj of response.Contents) {
222+
if (!obj.Key) continue;
223+
if (obj.Key && obj.Key.endsWith("/")) continue; // 跳过目录占位符
224+
if (obj.Key === this.basePath.slice(1)) continue; // 跳过 prefix 本身
197225

198-
// Skip the directory marker itself
199-
if (object.Key === prefix || object.Key.endsWith("/")) continue;
226+
// const name = obj.Key.substring(prefix.length);
227+
const relativeKey = obj.Key.slice(this.basePath.length);
228+
if (!relativeKey) continue;
200229

201-
const name = object.Key.substring(prefix.length);
202-
const lastModified = object.LastModified?.getTime() || Date.now();
230+
const lastModified = obj.LastModified?.getTime() || Date.now();
203231

204232
files.push({
205-
name,
233+
name: relativeKey,
206234
path: this.basePath,
207-
size: object.Size || 0,
208-
digest: object.ETag?.replace(/"/g, "") || "",
235+
size: obj.Size || 0,
236+
digest: obj.ETag?.replace(/"/g, "") || "",
209237
createtime: lastModified,
210238
updatetime: lastModified,
211239
});
@@ -215,6 +243,10 @@ export default class S3FileSystem implements FileSystem {
215243
continuationToken = response.NextContinuationToken;
216244
} while (continuationToken);
217245

246+
if (files.length > 10000) {
247+
console.warn(`Directory listing truncated: >10000 items under ${this.basePath}`);
248+
}
249+
218250
return files;
219251
} catch (error: any) {
220252
if (error.name === "AccessDenied") {

0 commit comments

Comments
 (0)