* fix(cloudreve): upload failure to return error msg instead of deletion success * fix(cloudreve): enable SetContentLength for uploading to local policy * refactor(cloudreve): move local policy upload logic to utils for better error handling * refactor(cloudreve): unified upload code style * refactor(cloudreve): improve user agent handling
This commit is contained in:
parent
9a9aee9ac6
commit
44cc71d354
@ -1,13 +1,10 @@
|
|||||||
package cloudreve
|
package cloudreve
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
@ -168,39 +165,13 @@ func (d *Cloudreve) Put(ctx context.Context, dstDir model.Obj, stream model.File
|
|||||||
case "remote": // 从机存储
|
case "remote": // 从机存储
|
||||||
err = d.upRemote(ctx, stream, u, up)
|
err = d.upRemote(ctx, stream, u, up)
|
||||||
case "local": // 本机存储
|
case "local": // 本机存储
|
||||||
var chunkSize = u.ChunkSize
|
err = d.upLocal(ctx, stream, u, up)
|
||||||
var buf []byte
|
|
||||||
var chunk int
|
|
||||||
for {
|
|
||||||
var n int
|
|
||||||
buf = make([]byte, chunkSize)
|
|
||||||
n, err = io.ReadAtLeast(stream, buf, chunkSize)
|
|
||||||
if err != nil && !errors.Is(err, io.ErrUnexpectedEOF) {
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if n == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
buf = buf[:n]
|
|
||||||
err = d.request(http.MethodPost, "/file/upload/"+u.SessionID+"/"+strconv.Itoa(chunk), func(req *resty.Request) {
|
|
||||||
req.SetHeader("Content-Type", "application/octet-stream")
|
|
||||||
req.SetHeader("Content-Length", strconv.Itoa(n))
|
|
||||||
req.SetBody(driver.NewLimitedUploadStream(ctx, bytes.NewReader(buf)))
|
|
||||||
}, nil)
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
chunk++
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
err = errs.NotImplement
|
err = errs.NotImplement
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// 删除失败的会话
|
// 删除失败的会话
|
||||||
err = d.request(http.MethodDelete, "/file/upload/"+u.SessionID, nil, nil)
|
_ = d.request(http.MethodDelete, "/file/upload/"+u.SessionID, nil, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -27,17 +27,20 @@ import (
|
|||||||
|
|
||||||
const loginPath = "/user/session"
|
const loginPath = "/user/session"
|
||||||
|
|
||||||
|
func (d *Cloudreve) getUA() string {
|
||||||
|
if d.CustomUA != "" {
|
||||||
|
return d.CustomUA
|
||||||
|
}
|
||||||
|
return base.UserAgent
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Cloudreve) request(method string, path string, callback base.ReqCallback, out interface{}) error {
|
func (d *Cloudreve) request(method string, path string, callback base.ReqCallback, out interface{}) error {
|
||||||
u := d.Address + "/api/v3" + path
|
u := d.Address + "/api/v3" + path
|
||||||
ua := d.CustomUA
|
|
||||||
if ua == "" {
|
|
||||||
ua = base.UserAgent
|
|
||||||
}
|
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeaders(map[string]string{
|
req.SetHeaders(map[string]string{
|
||||||
"Cookie": "cloudreve-session=" + d.Cookie,
|
"Cookie": "cloudreve-session=" + d.Cookie,
|
||||||
"Accept": "application/json, text/plain, */*",
|
"Accept": "application/json, text/plain, */*",
|
||||||
"User-Agent": ua,
|
"User-Agent": d.getUA(),
|
||||||
})
|
})
|
||||||
|
|
||||||
var r Resp
|
var r Resp
|
||||||
@ -161,15 +164,11 @@ func (d *Cloudreve) GetThumb(file Object) (model.Thumbnail, error) {
|
|||||||
if !d.Addition.EnableThumbAndFolderSize {
|
if !d.Addition.EnableThumbAndFolderSize {
|
||||||
return model.Thumbnail{}, nil
|
return model.Thumbnail{}, nil
|
||||||
}
|
}
|
||||||
ua := d.CustomUA
|
|
||||||
if ua == "" {
|
|
||||||
ua = base.UserAgent
|
|
||||||
}
|
|
||||||
req := base.NoRedirectClient.R()
|
req := base.NoRedirectClient.R()
|
||||||
req.SetHeaders(map[string]string{
|
req.SetHeaders(map[string]string{
|
||||||
"Cookie": "cloudreve-session=" + d.Cookie,
|
"Cookie": "cloudreve-session=" + d.Cookie,
|
||||||
"Accept": "image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
|
"Accept": "image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
|
||||||
"User-Agent": ua,
|
"User-Agent": d.getUA(),
|
||||||
})
|
})
|
||||||
resp, err := req.Execute(http.MethodGet, d.Address+"/api/v3/file/thumb/"+file.Id)
|
resp, err := req.Execute(http.MethodGet, d.Address+"/api/v3/file/thumb/"+file.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -180,6 +179,43 @@ func (d *Cloudreve) GetThumb(file Object) (model.Thumbnail, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Cloudreve) upLocal(ctx context.Context, stream model.FileStreamer, u UploadInfo, up driver.UpdateProgress) error {
|
||||||
|
var finish int64 = 0
|
||||||
|
var chunk int = 0
|
||||||
|
DEFAULT := int64(u.ChunkSize)
|
||||||
|
for finish < stream.GetSize() {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
utils.Log.Debugf("[Cloudreve-Local] upload: %d", finish)
|
||||||
|
var byteSize = DEFAULT
|
||||||
|
left := stream.GetSize() - finish
|
||||||
|
if left < DEFAULT {
|
||||||
|
byteSize = left
|
||||||
|
}
|
||||||
|
byteData := make([]byte, byteSize)
|
||||||
|
n, err := io.ReadFull(stream, byteData)
|
||||||
|
utils.Log.Debug(err, n)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = d.request(http.MethodPost, "/file/upload/"+u.SessionID+"/"+strconv.Itoa(chunk), func(req *resty.Request) {
|
||||||
|
req.SetHeader("Content-Type", "application/octet-stream")
|
||||||
|
req.SetContentLength(true)
|
||||||
|
req.SetHeader("Content-Length", strconv.FormatInt(byteSize, 10))
|
||||||
|
req.SetHeader("User-Agent", d.getUA())
|
||||||
|
req.SetBody(driver.NewLimitedUploadStream(ctx, bytes.NewBuffer(byteData)))
|
||||||
|
}, nil)
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
finish += byteSize
|
||||||
|
up(float64(finish) * 100 / float64(stream.GetSize()))
|
||||||
|
chunk++
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Cloudreve) upRemote(ctx context.Context, stream model.FileStreamer, u UploadInfo, up driver.UpdateProgress) error {
|
func (d *Cloudreve) upRemote(ctx context.Context, stream model.FileStreamer, u UploadInfo, up driver.UpdateProgress) error {
|
||||||
uploadUrl := u.UploadURLs[0]
|
uploadUrl := u.UploadURLs[0]
|
||||||
credential := u.Credential
|
credential := u.Credential
|
||||||
@ -211,6 +247,7 @@ func (d *Cloudreve) upRemote(ctx context.Context, stream model.FileStreamer, u U
|
|||||||
req.ContentLength = byteSize
|
req.ContentLength = byteSize
|
||||||
// req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
|
// req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
|
||||||
req.Header.Set("Authorization", fmt.Sprint(credential))
|
req.Header.Set("Authorization", fmt.Sprint(credential))
|
||||||
|
req.Header.Set("User-Agent", d.getUA())
|
||||||
finish += byteSize
|
finish += byteSize
|
||||||
res, err := base.HttpClient.Do(req)
|
res, err := base.HttpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -251,6 +288,7 @@ func (d *Cloudreve) upOneDrive(ctx context.Context, stream model.FileStreamer, u
|
|||||||
req.ContentLength = byteSize
|
req.ContentLength = byteSize
|
||||||
// req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
|
// req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
|
||||||
req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", finish, finish+byteSize-1, stream.GetSize()))
|
req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", finish, finish+byteSize-1, stream.GetSize()))
|
||||||
|
req.Header.Set("User-Agent", d.getUA())
|
||||||
finish += byteSize
|
finish += byteSize
|
||||||
res, err := base.HttpClient.Do(req)
|
res, err := base.HttpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user