feat(archive): support multipart archives (#8184 close #8015)

* feat(archive): multipart support & sevenzip tool

* feat(archive): rardecode tool

* feat(archive): support decompress multi-selected

* fix(archive): decompress response filter internal

* feat(archive): support multipart zip

* fix: more applicable AcceptedMultipartExtensions interface
This commit is contained in:
KirCute
2025-03-27 23:20:44 +08:00
committed by GitHub
parent 704d3854df
commit 1335f80362
19 changed files with 1042 additions and 320 deletions

View File

@ -139,7 +139,7 @@ type RateLimitRangeReadCloser struct {
Limiter Limiter
}
func (rrc RateLimitRangeReadCloser) RangeRead(ctx context.Context, httpRange http_range.Range) (io.ReadCloser, error) {
func (rrc *RateLimitRangeReadCloser) RangeRead(ctx context.Context, httpRange http_range.Range) (io.ReadCloser, error) {
rc, err := rrc.RangeReadCloserIF.RangeRead(ctx, httpRange)
if err != nil {
return nil, err

View File

@ -14,6 +14,7 @@ import (
"github.com/alist-org/alist/v3/pkg/http_range"
"github.com/alist-org/alist/v3/pkg/utils"
"github.com/sirupsen/logrus"
"go4.org/readerutil"
)
type FileStream struct {
@ -159,6 +160,10 @@ var _ model.FileStreamer = (*FileStream)(nil)
//var _ seekableStream = (*FileStream)(nil)
// for most internal stream, which is either RangeReadCloser or MFile
// Any functionality implemented based on SeekableStream should implement a Close method,
// whose only purpose is to close the SeekableStream object. If such functionality has
// additional resources that need to be closed, they should be added to the Closer property of
// the SeekableStream object and be closed together when the SeekableStream object is closed.
type SeekableStream struct {
FileStream
Link *model.Link
@ -196,7 +201,7 @@ func NewSeekableStream(fs FileStream, link *model.Link) (*SeekableStream, error)
return &ss, nil
}
if ss.Link.RangeReadCloser != nil {
ss.rangeReadCloser = RateLimitRangeReadCloser{
ss.rangeReadCloser = &RateLimitRangeReadCloser{
RangeReadCloserIF: ss.Link.RangeReadCloser,
Limiter: ServerDownloadLimit,
}
@ -208,7 +213,7 @@ func NewSeekableStream(fs FileStream, link *model.Link) (*SeekableStream, error)
if err != nil {
return nil, err
}
rrc = RateLimitRangeReadCloser{
rrc = &RateLimitRangeReadCloser{
RangeReadCloserIF: rrc,
Limiter: ServerDownloadLimit,
}
@ -364,7 +369,7 @@ type RangeReadReadAtSeeker struct {
ss *SeekableStream
masterOff int64
readers []*readerCur
*headCache
headCache *headCache
}
type headCache struct {
@ -406,7 +411,7 @@ func (c *headCache) read(p []byte) (n int, err error) {
}
return
}
func (r *headCache) close() error {
func (r *headCache) Close() error {
for i := range r.bufs {
r.bufs[i] = nil
}
@ -419,6 +424,7 @@ func (r *RangeReadReadAtSeeker) InitHeadCache() {
reader := r.readers[0]
r.readers = r.readers[1:]
r.headCache = &headCache{readerCur: reader}
r.ss.Closers.Add(r.headCache)
}
}
@ -449,6 +455,18 @@ func NewReadAtSeeker(ss *SeekableStream, offset int64, forceRange ...bool) (SStr
return r, nil
}
func NewMultiReaderAt(ss []*SeekableStream) (readerutil.SizeReaderAt, error) {
readers := make([]readerutil.SizeReaderAt, 0, len(ss))
for _, s := range ss {
ra, err := NewReadAtSeeker(s, 0)
if err != nil {
return nil, err
}
readers = append(readers, io.NewSectionReader(ra, 0, s.GetSize()))
}
return readerutil.NewMultiReaderAt(readers...), nil
}
func (r *RangeReadReadAtSeeker) GetRawStream() *SeekableStream {
return r.ss
}
@ -559,9 +577,6 @@ func (r *RangeReadReadAtSeeker) Read(p []byte) (n int, err error) {
}
func (r *RangeReadReadAtSeeker) Close() error {
if r.headCache != nil {
_ = r.headCache.close()
}
return r.ss.Close()
}