Skip to content

Commit 9033b55

Browse files
authored
feat(s3): implement Getter interface (#1790)
* feat(s3): implement Getter interface * update path * rm root
1 parent 07506b0 commit 9033b55

1 file changed

Lines changed: 72 additions & 0 deletions

File tree

drivers/s3/driver.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ import (
1616
"github.com/OpenListTeam/OpenList/v4/pkg/cron"
1717
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
1818
"github.com/OpenListTeam/OpenList/v4/server/common"
19+
"github.com/aws/aws-sdk-go/aws"
20+
"github.com/aws/aws-sdk-go/aws/awserr"
1921
"github.com/aws/aws-sdk-go/aws/session"
2022
"github.com/aws/aws-sdk-go/service/s3"
2123
"github.com/aws/aws-sdk-go/service/s3/s3manager"
24+
"github.com/pkg/errors"
2225
log "github.com/sirupsen/logrus"
2326
)
2427

@@ -243,4 +246,73 @@ func (d *S3) GetDirectUploadInfo(ctx context.Context, _ string, dstDir model.Obj
243246
}, nil
244247
}
245248

249+
// implements driver.Getter interface
250+
func (d *S3) Get(ctx context.Context, path string) (model.Obj, error) {
251+
// try to get object as a file using HeadObject
252+
key := getKey(stdpath.Join(d.GetRootPath(), path), false)
253+
headInput := &s3.HeadObjectInput{
254+
Bucket: &d.Bucket,
255+
Key: &key,
256+
}
257+
headOutput, err := d.client.HeadObjectWithContext(ctx, headInput)
258+
if err == nil {
259+
// Object exists as a file
260+
fileName := stdpath.Base(path)
261+
return &model.Object{
262+
Name: fileName,
263+
Size: *headOutput.ContentLength,
264+
Modified: *headOutput.LastModified,
265+
Path: path,
266+
}, nil
267+
}
268+
var awsErr awserr.Error
269+
if errors.As(err, &awsErr) && awsErr.Code() != "NotFound" {
270+
return nil, errors.WithMessage(err, "failed to head object")
271+
}
272+
273+
// If HeadObject fails with 404, check if it's a directory
274+
prefix := getKey(path, true)
275+
var contents []*s3.Object
276+
var commonPrefixes []*s3.CommonPrefix
277+
switch d.ListObjectVersion {
278+
case "v1":
279+
listInput := &s3.ListObjectsInput{
280+
Bucket: &d.Bucket,
281+
Prefix: &prefix,
282+
MaxKeys: aws.Int64(1), // Only need to check if at least one object exists
283+
}
284+
listResult, err := d.client.ListObjectsWithContext(ctx, listInput)
285+
if err != nil {
286+
return nil, errors.WithMessage(err, "failed to list objects with prefix")
287+
}
288+
contents = listResult.Contents
289+
commonPrefixes = listResult.CommonPrefixes
290+
case "v2":
291+
listInput := &s3.ListObjectsV2Input{
292+
Bucket: &d.Bucket,
293+
Prefix: &prefix,
294+
MaxKeys: aws.Int64(1),
295+
}
296+
listResult, err := d.client.ListObjectsV2WithContext(ctx, listInput)
297+
if err != nil {
298+
return nil, errors.WithMessage(err, "failed to list objects v2 with prefix")
299+
}
300+
contents = listResult.Contents
301+
commonPrefixes = listResult.CommonPrefixes
302+
default:
303+
return nil, fmt.Errorf("unsupported ListObjectVersion: %s", d.ListObjectVersion)
304+
}
305+
if len(contents) > 0 || len(commonPrefixes) > 0 {
306+
dirName := stdpath.Base(path + "/")
307+
return &model.Object{
308+
Name: dirName,
309+
Modified: d.Modified,
310+
IsFolder: true,
311+
Path: path,
312+
}, nil
313+
}
314+
return nil, errs.ObjectNotFound
315+
}
316+
246317
var _ driver.Driver = (*S3)(nil)
318+
var _ driver.Getter = (*S3)(nil)

0 commit comments

Comments
 (0)