Files
OpenList/internal/offline_download/http/client.go

106 lines
2.4 KiB
Go

package http
import (
"fmt"
"math/rand/v2"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
"github.com/OpenListTeam/OpenList/v4/internal/model"
"github.com/OpenListTeam/OpenList/v4/internal/offline_download/tool"
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
)
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 {
streamPut := task.DeletePolicy == tool.UploadDownloadStream
method := http.MethodGet
if streamPut {
method = http.MethodHead
}
req, err := http.NewRequestWithContext(task.Ctx(), method, task.Url, nil)
if err != nil {
return err
}
if streamPut {
req.Header.Set("Range", "bytes=0-")
}
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, err := parseFilenameFromContentDisposition(resp.Header.Get("Content-Disposition"))
if err != nil {
filename = path.Base(resp.Request.URL.Path)
}
filename = strings.Trim(filename, "/")
if len(filename) == 0 {
filename = fmt.Sprintf("%s-%d-%x", strings.ReplaceAll(req.URL.Host, ".", "_"), time.Now().UnixMilli(), rand.Uint32())
}
fileSize := resp.ContentLength
if streamPut {
if fileSize == 0 {
start, end, _ := http_range.ParseContentRange(resp.Header.Get("Content-Range"))
fileSize = start + end
}
task.SetTotalBytes(fileSize)
task.TempDir = filename
return nil
}
task.SetTotalBytes(fileSize)
// 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()
err = utils.CopyWithCtx(task.Ctx(), file, resp.Body, fileSize, task.SetProgress)
return err
}
func init() {
tool.Tools.Add(&SimpleHttp{})
}