feat(offline_download): add simple http tool (close #4002)
This commit is contained in:
parent
b6134dc515
commit
34746e951c
@ -29,3 +29,7 @@ func NewErr(err error, format string, a ...any) error {
|
|||||||
func IsNotFoundError(err error) bool {
|
func IsNotFoundError(err error) bool {
|
||||||
return errors.Is(pkgerr.Cause(err), ObjectNotFound) || errors.Is(pkgerr.Cause(err), StorageNotFound)
|
return errors.Is(pkgerr.Cause(err), ObjectNotFound) || errors.Is(pkgerr.Cause(err), StorageNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsNotSupportError(err error) bool {
|
||||||
|
return errors.Is(pkgerr.Cause(err), NotSupport)
|
||||||
|
}
|
||||||
|
@ -2,5 +2,6 @@ package offline_download
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "github.com/alist-org/alist/v3/internal/offline_download/aria2"
|
_ "github.com/alist-org/alist/v3/internal/offline_download/aria2"
|
||||||
|
_ "github.com/alist-org/alist/v3/internal/offline_download/http"
|
||||||
_ "github.com/alist-org/alist/v3/internal/offline_download/qbit"
|
_ "github.com/alist-org/alist/v3/internal/offline_download/qbit"
|
||||||
)
|
)
|
||||||
|
@ -3,6 +3,7 @@ package aria2
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -21,6 +22,10 @@ type Aria2 struct {
|
|||||||
client rpc.Client
|
client rpc.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Aria2) Run(task *tool.DownloadTask) error {
|
||||||
|
return errs.NotSupport
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Aria2) Name() string {
|
func (a *Aria2) Name() string {
|
||||||
return "aria2"
|
return "aria2"
|
||||||
}
|
}
|
||||||
|
85
internal/offline_download/http/client.go
Normal file
85
internal/offline_download/http/client.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/offline_download/tool"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SimpleHttp struct {
|
||||||
|
client http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) Name() string {
|
||||||
|
return "SimpleHttp"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) Items() []model.SettingItem {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) Init() (string, error) {
|
||||||
|
return "ok", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) IsReady() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) AddURL(args *tool.AddUrlArgs) (string, error) {
|
||||||
|
panic("should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) Remove(task *tool.DownloadTask) error {
|
||||||
|
panic("should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) Status(task *tool.DownloadTask) (*tool.Status, error) {
|
||||||
|
panic("should not be called")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s SimpleHttp) Run(task *tool.DownloadTask) error {
|
||||||
|
u := task.Url
|
||||||
|
// parse url
|
||||||
|
_u, err := url.Parse(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req, err := http.NewRequestWithContext(task.Ctx(), http.MethodGet, u, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp, err := s.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode >= 400 {
|
||||||
|
return fmt.Errorf("http status code %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
filename := path.Base(_u.Path)
|
||||||
|
if n, err := parseFilenameFromContentDisposition(resp.Header.Get("Content-Disposition")); err == nil {
|
||||||
|
filename = n
|
||||||
|
}
|
||||||
|
// save to temp dir
|
||||||
|
_ = os.MkdirAll(task.TempDir, os.ModePerm)
|
||||||
|
filePath := filepath.Join(task.TempDir, filename)
|
||||||
|
file, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
fileSize := resp.ContentLength
|
||||||
|
err = utils.CopyWithCtx(task.Ctx(), file, resp.Body, fileSize, task.SetProgress)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
tool.Tools.Add(&SimpleHttp{})
|
||||||
|
}
|
21
internal/offline_download/http/util.go
Normal file
21
internal/offline_download/http/util.go
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"mime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseFilenameFromContentDisposition(contentDisposition string) (string, error) {
|
||||||
|
if contentDisposition == "" {
|
||||||
|
return "", fmt.Errorf("Content-Disposition is empty")
|
||||||
|
}
|
||||||
|
_, params, err := mime.ParseMediaType(contentDisposition)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
filename := params["filename"]
|
||||||
|
if filename == "" {
|
||||||
|
return "", fmt.Errorf("filename not found in Content-Disposition: [%s]", contentDisposition)
|
||||||
|
}
|
||||||
|
return filename, nil
|
||||||
|
}
|
@ -2,6 +2,7 @@ package qbit
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/offline_download/tool"
|
"github.com/alist-org/alist/v3/internal/offline_download/tool"
|
||||||
"github.com/alist-org/alist/v3/internal/setting"
|
"github.com/alist-org/alist/v3/internal/setting"
|
||||||
@ -13,6 +14,10 @@ type QBittorrent struct {
|
|||||||
client qbittorrent.Client
|
client qbittorrent.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *QBittorrent) Run(task *tool.DownloadTask) error {
|
||||||
|
return errs.NotSupport
|
||||||
|
}
|
||||||
|
|
||||||
func (a *QBittorrent) Name() string {
|
func (a *QBittorrent) Name() string {
|
||||||
return "qBittorrent"
|
return "qBittorrent"
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,9 @@ type Tool interface {
|
|||||||
Remove(task *DownloadTask) error
|
Remove(task *DownloadTask) error
|
||||||
// Status return the status of the download task, if an error occurred, return the error in Status.Err
|
// Status return the status of the download task, if an error occurred, return the error in Status.Err
|
||||||
Status(task *DownloadTask) (*Status, error)
|
Status(task *DownloadTask) (*Status, error)
|
||||||
|
|
||||||
|
// Run for simple http download
|
||||||
|
Run(task *DownloadTask) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetFileser interface {
|
type GetFileser interface {
|
||||||
|
@ -2,6 +2,7 @@ package tool
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/xhofe/tache"
|
"github.com/xhofe/tache"
|
||||||
@ -25,6 +26,12 @@ type DownloadTask struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *DownloadTask) Run() error {
|
func (t *DownloadTask) Run() error {
|
||||||
|
if err := t.tool.Run(t); !errs.IsNotSupportError(err) {
|
||||||
|
if err == nil {
|
||||||
|
return t.Complete()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
t.Signal = make(chan int)
|
t.Signal = make(chan int)
|
||||||
t.finish = make(chan struct{})
|
t.finish = make(chan struct{})
|
||||||
defer func() {
|
defer func() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user