feat(ftp-server): support resumable downloading (#7792)

This commit is contained in:
KirCute_ECT
2025-01-10 20:50:20 +08:00
committed by GitHub
parent 6812ec9a6d
commit 25b4b55ee1
5 changed files with 52 additions and 17 deletions

View File

@ -83,9 +83,6 @@ func (a *AferoAdapter) ReadDir(name string) ([]os.FileInfo, error) {
func (a *AferoAdapter) GetHandle(name string, flags int, offset int64) (ftpserver.FileTransfer, error) {
fileSize := a.nextFileSize
a.nextFileSize = 0
if offset != 0 {
return nil, errs.NotSupport
}
if (flags & os.O_SYNC) != 0 {
return nil, errs.NotSupport
}
@ -106,6 +103,9 @@ func (a *AferoAdapter) GetHandle(name string, flags int, offset int64) (ftpserve
return nil, errors.New("file already exists")
}
if (flags & os.O_WRONLY) != 0 {
if offset != 0 {
return nil, errs.NotSupport
}
trunc := (flags & os.O_TRUNC) != 0
if fileSize > 0 {
return OpenUploadWithLength(a.ctx, path, trunc, fileSize)
@ -113,7 +113,7 @@ func (a *AferoAdapter) GetHandle(name string, flags int, offset int64) (ftpserve
return OpenUpload(a.ctx, path, trunc)
}
}
return OpenDownload(a.ctx, path)
return OpenDownload(a.ctx, path, offset)
}
func (a *AferoAdapter) SetNextFileSize(size int64) {

View File

@ -8,6 +8,7 @@ import (
"github.com/alist-org/alist/v3/internal/model"
"github.com/alist-org/alist/v3/internal/op"
"github.com/alist-org/alist/v3/internal/stream"
"github.com/alist-org/alist/v3/pkg/http_range"
"github.com/alist-org/alist/v3/server/common"
"github.com/pkg/errors"
"io"
@ -19,10 +20,12 @@ import (
type FileDownloadProxy struct {
ftpserver.FileTransfer
reader io.ReadCloser
ss *stream.SeekableStream
reader io.Reader
cur int64
}
func OpenDownload(ctx context.Context, reqPath string) (*FileDownloadProxy, error) {
func OpenDownload(ctx context.Context, reqPath string, offset int64) (*FileDownloadProxy, error) {
user := ctx.Value("user").(*model.User)
meta, err := op.GetNearestMeta(reqPath)
if err != nil {
@ -52,11 +55,22 @@ func OpenDownload(ctx context.Context, reqPath string) (*FileDownloadProxy, erro
if err != nil {
return nil, err
}
return &FileDownloadProxy{reader: ss}, nil
var reader io.Reader
if offset != 0 {
reader, err = ss.RangeRead(http_range.Range{Start: offset, Length: -1})
if err != nil {
return nil, err
}
} else {
reader = ss
}
return &FileDownloadProxy{ss: ss, reader: reader}, nil
}
func (f *FileDownloadProxy) Read(p []byte) (n int, err error) {
return f.reader.Read(p)
n, err = f.reader.Read(p)
f.cur += int64(n)
return n, err
}
func (f *FileDownloadProxy) Write(p []byte) (n int, err error) {
@ -64,11 +78,32 @@ func (f *FileDownloadProxy) Write(p []byte) (n int, err error) {
}
func (f *FileDownloadProxy) Seek(offset int64, whence int) (int64, error) {
return 0, errs.NotSupport
switch whence {
case io.SeekStart:
break
case io.SeekCurrent:
offset += f.cur
break
case io.SeekEnd:
offset += f.ss.GetSize()
break
default:
return 0, errs.NotSupport
}
if offset < 0 {
return 0, errors.New("Seek: negative position")
}
reader, err := f.ss.RangeRead(http_range.Range{Start: offset, Length: -1})
if err != nil {
return f.cur, err
}
f.cur = offset
f.reader = reader
return offset, nil
}
func (f *FileDownloadProxy) Close() error {
return f.reader.Close()
return f.ss.Close()
}
type OsFileInfoAdapter struct {

View File

@ -63,7 +63,7 @@ func (f *FileUploadProxy) Write(p []byte) (n int, err error) {
}
func (f *FileUploadProxy) Seek(offset int64, whence int) (int64, error) {
return 0, errs.NotSupport
return f.buffer.Seek(offset, whence)
}
func (f *FileUploadProxy) Close() error {