refactor: optimize stream, link, and resource management (#486)

* refactor: optimize stream, link, and resource management

* Link.MFile改为io.ReadSeeker类型

* fix (crypt): read on closed response body

* chore

* chore

* chore
This commit is contained in:
j2rong4cn
2025-07-03 10:39:34 +08:00
committed by GitHub
parent 8e19a0fb07
commit ffb6c2a180
26 changed files with 180 additions and 275 deletions

View File

@@ -5,7 +5,6 @@ import (
"fmt"
"io"
"net/http"
"os"
"strings"
"maps"
@@ -19,21 +18,15 @@ import (
func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.Obj) error {
if link.MFile != nil {
defer link.MFile.Close()
if clr, ok := link.MFile.(io.Closer); ok {
defer clr.Close()
}
attachHeader(w, file)
contentType := link.Header.Get("Content-Type")
if contentType != "" {
w.Header().Set("Content-Type", contentType)
}
mFile := link.MFile
if _, ok := mFile.(*os.File); !ok {
mFile = &stream.RateLimitFile{
File: mFile,
Limiter: stream.ServerDownloadLimit,
Ctx: r.Context(),
}
}
http.ServeContent(w, r, file.GetName(), file.ModTime(), mFile)
http.ServeContent(w, r, file.GetName(), file.ModTime(), link.MFile)
return nil
} else if link.RangeReadCloser != nil {
attachHeader(w, file)

View File

@@ -2,6 +2,7 @@ package ftp
import (
"context"
"io"
fs2 "io/fs"
"net/http"
"os"
@@ -13,13 +14,13 @@ import (
"github.com/OpenListTeam/OpenList/v4/internal/op"
"github.com/OpenListTeam/OpenList/v4/internal/stream"
"github.com/OpenListTeam/OpenList/v4/server/common"
ftpserver "github.com/fclairamb/ftpserverlib"
"github.com/pkg/errors"
)
type FileDownloadProxy struct {
ftpserver.FileTransfer
reader stream.SStreamReadAtSeeker
model.File
io.Closer
ctx context.Context
}
func OpenDownload(ctx context.Context, reqPath string, offset int64) (*FileDownloadProxy, error) {
@@ -57,15 +58,24 @@ func OpenDownload(ctx context.Context, reqPath string, offset int64) (*FileDownl
_ = ss.Close()
return nil, err
}
return &FileDownloadProxy{reader: reader}, nil
return &FileDownloadProxy{File: reader, Closer: ss, ctx: ctx}, nil
}
func (f *FileDownloadProxy) Read(p []byte) (n int, err error) {
n, err = f.reader.Read(p)
n, err = f.File.Read(p)
if err != nil {
return
}
err = stream.ClientDownloadLimit.WaitN(f.reader.GetRawStream().Ctx, n)
err = stream.ClientDownloadLimit.WaitN(f.ctx, n)
return
}
func (f *FileDownloadProxy) ReadAt(p []byte, off int64) (n int, err error) {
n, err = f.File.ReadAt(p, off)
if err != nil {
return
}
err = stream.ClientDownloadLimit.WaitN(f.ctx, n)
return
}
@@ -73,14 +83,6 @@ func (f *FileDownloadProxy) Write(p []byte) (n int, err error) {
return 0, errs.NotSupport
}
func (f *FileDownloadProxy) Seek(offset int64, whence int) (int64, error) {
return f.reader.Seek(offset, whence)
}
func (f *FileDownloadProxy) Close() error {
return f.reader.Close()
}
type OsFileInfoAdapter struct {
obj model.Obj
}

View File

@@ -85,15 +85,15 @@ func Proxy(c *gin.Context) {
}
func down(c *gin.Context, link *model.Link) {
var err error
if link.MFile != nil {
defer func(ReadSeekCloser io.ReadCloser) {
err := ReadSeekCloser.Close()
if clr, ok := link.MFile.(io.Closer); ok {
defer func(clr io.Closer) {
err := clr.Close()
if err != nil {
log.Errorf("close data error: %s", err)
log.Errorf("close link data error: %v", err)
}
}(link.MFile)
}(clr)
}
var err error
c.Header("Referrer-Policy", "no-referrer")
c.Header("Cache-Control", "max-age=0, no-cache, no-store, must-revalidate")
if setting.GetBool(conf.ForwardDirectLinkParams) {

View File

@@ -390,14 +390,13 @@ func Link(c *gin.Context) {
common.ErrorResp(c, err, 500)
return
}
if link.MFile != nil {
defer func(ReadSeekCloser io.ReadCloser) {
err := ReadSeekCloser.Close()
if clr, ok := link.MFile.(io.Closer); ok {
defer func(clr io.Closer) {
err := clr.Close()
if err != nil {
log.Errorf("close link data error: %v", err)
}
}(link.MFile)
}(clr)
}
common.SuccessResp(c, link)
return
}

View File

@@ -187,7 +187,11 @@ func (b *s3Backend) GetObject(ctx context.Context, bucketName, objectName string
if err != nil {
return nil, err
}
rdr = link.MFile
if rdr2, ok := link.MFile.(io.ReadCloser); ok {
rdr = rdr2
} else {
rdr = io.NopCloser(link.MFile)
}
} else {
remoteFileSize := file.GetSize()
if length >= 0 && start+length >= remoteFileSize {