From 7f0de8422c5442f7255c8cb2503e3c64aac9aff9 Mon Sep 17 00:00:00 2001 From: MadDogOwner Date: Thu, 13 Nov 2025 10:11:13 +0800 Subject: [PATCH 1/4] feat(onedrive): support create share link for download Signed-off-by: MadDogOwner --- drivers/onedrive/driver.go | 25 +++++++++++++------- drivers/onedrive/meta.go | 1 + drivers/onedrive/util.go | 48 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 8 deletions(-) diff --git a/drivers/onedrive/driver.go b/drivers/onedrive/driver.go index b460853ee..358bfd741 100644 --- a/drivers/onedrive/driver.go +++ b/drivers/onedrive/driver.go @@ -105,16 +105,25 @@ func (d *Onedrive) List(ctx context.Context, dir model.Obj, args model.ListArgs) } func (d *Onedrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { - f, err := d.GetFile(file.GetPath()) - if err != nil { - return nil, err - } - if f.File == nil { - return nil, errs.NotFile + var u string + var err error + if d.CreateShareLink { + u, err = d.createLink(file.GetPath()) + if err != nil { + return nil, err + } + } else { + f, err := d.GetFile(file.GetPath()) + if err != nil { + return nil, err + } + if f.File == nil { + return nil, errs.NotFile + } + u = f.Url } - u := f.Url if d.CustomHost != "" { - _u, err := url.Parse(f.Url) + _u, err := url.Parse(u) if err != nil { return nil, err } diff --git a/drivers/onedrive/meta.go b/drivers/onedrive/meta.go index 4fd505b9c..83d6aa8d5 100644 --- a/drivers/onedrive/meta.go +++ b/drivers/onedrive/meta.go @@ -20,6 +20,7 @@ type Addition struct { CustomHost string `json:"custom_host" help:"Custom host for onedrive download link"` DisableDiskUsage bool `json:"disable_disk_usage" default:"false"` EnableDirectUpload bool `json:"enable_direct_upload" default:"false" help:"Enable direct upload from client to OneDrive"` + CreateShareLink bool `json:"create_share_link" default:"false" help:"Create share link for file download"` } var config = driver.Config{ diff --git a/drivers/onedrive/util.go b/drivers/onedrive/util.go index ad300af44..6b1b1ce08 100644 --- a/drivers/onedrive/util.go +++ b/drivers/onedrive/util.go @@ -6,7 +6,9 @@ import ( "fmt" "io" "net/http" + "net/url" stdpath "path" + "strings" "time" "github.com/OpenListTeam/OpenList/v4/drivers/base" @@ -185,6 +187,52 @@ func (d *Onedrive) GetFile(path string) (*File, error) { return &file, err } +func (d *Onedrive) createLink(path string) (string, error) { + api := d.GetMetaUrl(false, path) + "/createLink" + data := base.Json{ + "type": "view", + "scope": "anonymous", + } + var resp struct { + Link struct { + WebUrl string `json:"webUrl"` + } `json:"link"` + } + _, err := d.Request(api, http.MethodPost, func(req *resty.Request) { + req.SetBody(data) + }, &resp) + if err != nil { + return "", err + } + + p, err := url.Parse(resp.Link.WebUrl) + if err != nil { + return "", err + } + q := p.Query() + + if p.Host == "1drv.ms" { + // For personal, do some transformations + // https://1drv.ms/u/c/{user}/{share}?e=xxxx -> + // https://my.microsoftpersonalcontent.com/personal/{user}/_layouts/15/download.aspx?share={share} + paths := strings.Split(p.Path, "/") + if len(paths) < 4 || paths[2] == "" || paths[3] == "" { + return "", fmt.Errorf("invalid onedrive short link") + } + user := paths[2] + share := paths[3] + p.Scheme = "https" + p.Host = "my.microsoftpersonalcontent.com" + p.Path = fmt.Sprintf("/personal/%s/_layouts/15/download.aspx", user) + q = url.Values{} + q.Set("share", share) + } else { + q.Set("download", "1") + } + p.RawQuery = q.Encode() + return p.String(), nil +} + func (d *Onedrive) upSmall(ctx context.Context, dstDir model.Obj, stream model.FileStreamer) error { filepath := stdpath.Join(dstDir.GetPath(), stream.GetName()) // 1. upload new file From e1b30c7f934187951b62ff1ed1db48dbcf316d91 Mon Sep 17 00:00:00 2001 From: MadDogOwner Date: Thu, 13 Nov 2025 10:19:46 +0800 Subject: [PATCH 2/4] feat(onedrive): add expiration duration for link Signed-off-by: MadDogOwner --- drivers/onedrive/driver.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/onedrive/driver.go b/drivers/onedrive/driver.go index 358bfd741..e62c4008d 100644 --- a/drivers/onedrive/driver.go +++ b/drivers/onedrive/driver.go @@ -7,6 +7,7 @@ import ( "net/url" "path" "sync" + "time" "github.com/OpenListTeam/OpenList/v4/drivers/base" "github.com/OpenListTeam/OpenList/v4/internal/driver" @@ -107,12 +108,15 @@ func (d *Onedrive) List(ctx context.Context, dir model.Obj, args model.ListArgs) func (d *Onedrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { var u string var err error + var duration time.Duration if d.CreateShareLink { + duration = 365 * 24 * time.Hour // cache 1 year u, err = d.createLink(file.GetPath()) if err != nil { return nil, err } } else { + duration = 5 * time.Minute // cache 5 min f, err := d.GetFile(file.GetPath()) if err != nil { return nil, err @@ -131,7 +135,8 @@ func (d *Onedrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs u = _u.String() } return &model.Link{ - URL: u, + URL: u, + Expiration: &duration, }, nil } From 533397a1ef4af550f851f45110d769b496811fce Mon Sep 17 00:00:00 2001 From: MadDogOwner Date: Thu, 13 Nov 2025 10:39:57 +0800 Subject: [PATCH 3/4] fix(onedrive): fix path parsing for personal OneDrive short links Signed-off-by: MadDogOwner --- drivers/onedrive/util.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/onedrive/util.go b/drivers/onedrive/util.go index 6b1b1ce08..9143112e3 100644 --- a/drivers/onedrive/util.go +++ b/drivers/onedrive/util.go @@ -213,14 +213,14 @@ func (d *Onedrive) createLink(path string) (string, error) { if p.Host == "1drv.ms" { // For personal, do some transformations - // https://1drv.ms/u/c/{user}/{share}?e=xxxx -> + // https://1drv.ms/t/c/{user}/{share} -> // https://my.microsoftpersonalcontent.com/personal/{user}/_layouts/15/download.aspx?share={share} paths := strings.Split(p.Path, "/") - if len(paths) < 4 || paths[2] == "" || paths[3] == "" { + if len(paths) < 5 || paths[3] == "" || paths[4] == "" { return "", fmt.Errorf("invalid onedrive short link") } - user := paths[2] - share := paths[3] + user := paths[3] + share := paths[4] p.Scheme = "https" p.Host = "my.microsoftpersonalcontent.com" p.Path = fmt.Sprintf("/personal/%s/_layouts/15/download.aspx", user) From 3f8d8bf28f4c35ab7bebbdfd72916cf7806724b8 Mon Sep 17 00:00:00 2001 From: MadDogOwner Date: Thu, 20 Nov 2025 12:24:39 +0800 Subject: [PATCH 4/4] fix(onedrive): use download.aspx for all Signed-off-by: MadDogOwner --- drivers/onedrive/util.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/onedrive/util.go b/drivers/onedrive/util.go index 9143112e3..c4b94e5b6 100644 --- a/drivers/onedrive/util.go +++ b/drivers/onedrive/util.go @@ -209,10 +209,10 @@ func (d *Onedrive) createLink(path string) (string, error) { if err != nil { return "", err } - q := p.Query() - + // Do some transformations + q := url.Values{} if p.Host == "1drv.ms" { - // For personal, do some transformations + // For personal // https://1drv.ms/t/c/{user}/{share} -> // https://my.microsoftpersonalcontent.com/personal/{user}/_layouts/15/download.aspx?share={share} paths := strings.Split(p.Path, "/") @@ -221,13 +221,22 @@ func (d *Onedrive) createLink(path string) (string, error) { } user := paths[3] share := paths[4] - p.Scheme = "https" p.Host = "my.microsoftpersonalcontent.com" p.Path = fmt.Sprintf("/personal/%s/_layouts/15/download.aspx", user) - q = url.Values{} + q.Set("share", share) + } else if strings.Contains(p.Host, ".sharepoint.com") { + // https://{tenant}-my.sharepoint.com/:u:/g/personal/{user_email}/{share} + // https://{tenant}-my.sharepoint.com/personal/{user_email}/_layouts/15/download.aspx?share={share} + paths := strings.Split(p.Path, "/") + if len(paths) < 6 || paths[5] == "" { + return "", fmt.Errorf("invalid onedrive sharepoint link") + } + user := paths[4] + share := paths[5] + p.Path = fmt.Sprintf("/personal/%s/_layouts/15/download.aspx", user) q.Set("share", share) } else { - q.Set("download", "1") + return "", fmt.Errorf("unsupported onedrive link host: %s", p.Host) } p.RawQuery = q.Encode() return p.String(), nil