mirror of https://github.com/Xhofe/alist
				
				
				
			feat(quark): shard request file (close #4175)
							parent
							
								
									7f35aab071
								
							
						
					
					
						commit
						8711f2a1c5
					
				| 
						 | 
				
			
			@ -5,15 +5,18 @@ import (
 | 
			
		|||
	"crypto/md5"
 | 
			
		||||
	"crypto/sha1"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/alist-org/alist/v3/drivers/base"
 | 
			
		||||
	"github.com/alist-org/alist/v3/internal/driver"
 | 
			
		||||
	"github.com/alist-org/alist/v3/internal/errs"
 | 
			
		||||
	"github.com/alist-org/alist/v3/internal/model"
 | 
			
		||||
	"github.com/alist-org/alist/v3/pkg/http_range"
 | 
			
		||||
	"github.com/alist-org/alist/v3/pkg/utils"
 | 
			
		||||
	"github.com/go-resty/resty/v2"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
| 
						 | 
				
			
			@ -64,12 +67,58 @@ func (d *Quark) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	u := resp.Data[0].DownloadUrl
 | 
			
		||||
	start, end := int64(0), file.GetSize()
 | 
			
		||||
	return &model.Link{
 | 
			
		||||
		URL: resp.Data[0].DownloadUrl,
 | 
			
		||||
		Header: http.Header{
 | 
			
		||||
			"Cookie":     []string{d.Cookie},
 | 
			
		||||
			"Referer":    []string{"https://pan.quark.cn"},
 | 
			
		||||
			"User-Agent": []string{ua},
 | 
			
		||||
		Handle: func(w http.ResponseWriter, r *http.Request) error {
 | 
			
		||||
			if rg := r.Header.Get("Range"); rg != "" {
 | 
			
		||||
				parseRange, err := http_range.ParseRange(rg, file.GetSize())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				start, end = parseRange[0].Start, parseRange[0].Start+parseRange[0].Length
 | 
			
		||||
				w.Header().Set("Content-Range", parseRange[0].ContentRange(file.GetSize()))
 | 
			
		||||
				w.Header().Set("Content-Length", strconv.FormatInt(parseRange[0].Length, 10))
 | 
			
		||||
				w.WriteHeader(http.StatusPartialContent)
 | 
			
		||||
			} else {
 | 
			
		||||
				w.Header().Set("Content-Length", strconv.FormatInt(file.GetSize(), 10))
 | 
			
		||||
				w.WriteHeader(http.StatusOK)
 | 
			
		||||
			}
 | 
			
		||||
			// request 10 MB at a time
 | 
			
		||||
			chunkSize := int64(10 * 1024 * 1024)
 | 
			
		||||
			for start < end {
 | 
			
		||||
				_end := start + chunkSize
 | 
			
		||||
				if _end > end {
 | 
			
		||||
					_end = end
 | 
			
		||||
				}
 | 
			
		||||
				_range := "bytes=" + strconv.FormatInt(start, 10) + "-" + strconv.FormatInt(_end-1, 10)
 | 
			
		||||
				start = _end
 | 
			
		||||
				err = func() error {
 | 
			
		||||
					req, err := http.NewRequest(r.Method, u, nil)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					req.Header.Set("Range", _range)
 | 
			
		||||
					req.Header.Set("User-Agent", ua)
 | 
			
		||||
					req.Header.Set("Cookie", d.Cookie)
 | 
			
		||||
					req.Header.Set("Referer", "https://pan.quark.cn")
 | 
			
		||||
					resp, err := http.DefaultClient.Do(req)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					defer resp.Body.Close()
 | 
			
		||||
					if resp.StatusCode != http.StatusPartialContent {
 | 
			
		||||
						return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
 | 
			
		||||
					}
 | 
			
		||||
					_, err = io.Copy(w, resp.Body)
 | 
			
		||||
					return err
 | 
			
		||||
				}()
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ type Addition struct {
 | 
			
		|||
 | 
			
		||||
var config = driver.Config{
 | 
			
		||||
	Name:              "Quark",
 | 
			
		||||
	OnlyProxy:   true,
 | 
			
		||||
	OnlyLocal:         true,
 | 
			
		||||
	DefaultRoot:       "0",
 | 
			
		||||
	NoOverwriteUpload: true,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ type Link struct {
 | 
			
		|||
	Status     int                                                // status maybe 200 or 206, etc
 | 
			
		||||
	FilePath   *string                                            // local file, return the filepath
 | 
			
		||||
	Expiration *time.Duration                                     // url expiration time
 | 
			
		||||
	Handle     func(w http.ResponseWriter, r *http.Request) error // custom handler
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type OtherArgs struct {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,8 @@ func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.
 | 
			
		|||
		w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"; filename*=UTF-8''%s`, filename, url.PathEscape(filename)))
 | 
			
		||||
		http.ServeContent(w, r, file.GetName(), fileStat.ModTime(), f)
 | 
			
		||||
		return nil
 | 
			
		||||
	} else if link.Handle != nil {
 | 
			
		||||
		return link.Handle(w, r)
 | 
			
		||||
	} else {
 | 
			
		||||
		req, err := http.NewRequest(r.Method, link.URL, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,7 @@ import (
 | 
			
		|||
	"github.com/alist-org/alist/v3/internal/sign"
 | 
			
		||||
	"github.com/alist-org/alist/v3/pkg/utils"
 | 
			
		||||
	"github.com/alist-org/alist/v3/server/common"
 | 
			
		||||
	log "github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Handler struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -237,6 +238,7 @@ func (h *Handler) handleGetHeadPost(w http.ResponseWriter, r *http.Request) (sta
 | 
			
		|||
		}
 | 
			
		||||
		err = common.Proxy(w, r, link, fi)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Errorf("webdav proxy error: %+v", err)
 | 
			
		||||
			return http.StatusInternalServerError, err
 | 
			
		||||
		}
 | 
			
		||||
	} else if storage.GetStorage().WebdavProxy() && downProxyUrl != "" {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue