Feat: get OneDrive thumbnails

This commit is contained in:
HFO4
2020-01-21 13:27:20 +08:00
parent 6aee31341f
commit 06ff8b5a50
7 changed files with 94 additions and 12 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
model "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/cache"
"github.com/HFO4/cloudreve/pkg/request"
@@ -18,6 +19,13 @@ import (
"time"
)
const (
// SmallFileSize 单文件上传接口最大尺寸
SmallFileSize uint64 = 4 * 1024 * 1024
// ChunkSize 分片上传分片大小
ChunkSize uint64 = 10 * 1024 * 1024
)
// GetSourcePath 获取文件的绝对路径
func (info *FileInfo) GetSourcePath() string {
res, err := url.PathUnescape(
@@ -209,11 +217,41 @@ func (client *Client) makeBatchDeleteRequestsBody(files []string) string {
return string(res)
}
// GetThumbURL 获取给定尺寸的缩略图URL
func (client *Client) GetThumbURL(ctx context.Context, dst string, w, h uint) (string, error) {
dst = strings.TrimPrefix(dst, "/")
cropOption := fmt.Sprintf("c%dx%d_Crop", w, h)
requestURL := client.getRequestURL("me/drive/root:/"+dst+":/thumbnails") + "?select=" + cropOption
res, err := client.requestWithStr(ctx, "GET", requestURL, "", 200)
if err != nil {
return "", err
}
var (
decodeErr error
thumbRes ThumbResponse
)
decodeErr = json.Unmarshal([]byte(res), &thumbRes)
if decodeErr != nil {
return "", decodeErr
}
if len(thumbRes.Value) == 1 {
if res, ok := thumbRes.Value[0][cropOption]; ok {
return res.(map[string]interface{})["url"].(string), nil
}
}
return "", errors.New("无法生成缩略图")
}
// MonitorUpload 监控客户端分片上传进度
func (client *Client) MonitorUpload(uploadURL, callbackKey, path string, size uint64, ttl int64) {
// 回调完成通知chan
callbackChan := make(chan bool)
callbackSignal.Store(callbackKey, callbackChan)
defer callbackSignal.Delete(callbackKey)
timeout := model.GetIntSetting("onedrive_monitor_timeout", 600)
interval := model.GetIntSetting("onedrive_callback_check", 20)
@@ -339,7 +377,7 @@ func (client *Client) request(ctx context.Context, method string, url string, bo
if res.Response.StatusCode != expectedCode {
decodeErr = json.Unmarshal([]byte(respBody), &errResp)
if decodeErr != nil {
return "", sysError(err)
return "", sysError(decodeErr)
}
return "", &errResp
}

View File

@@ -24,7 +24,9 @@ func (handler Driver) Get(ctx context.Context, path string) (response.RSCloser,
// Put 将文件流保存到指定目录
func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, size uint64) error {
return errors.New("未实现")
defer file.Close()
_, err := handler.Client.PutFile(ctx, dst, file)
return err
}
// Delete 删除一个或多个文件,
@@ -35,7 +37,25 @@ func (handler Driver) Delete(ctx context.Context, files []string) ([]string, err
// Thumb 获取文件缩略图
func (handler Driver) Thumb(ctx context.Context, path string) (*response.ContentResponse, error) {
return nil, errors.New("未实现")
var (
thumbSize = [2]uint{400, 300}
ok = false
)
if thumbSize, ok = ctx.Value(fsctx.ThumbSizeCtx).([2]uint); !ok {
return nil, errors.New("无法获取缩略图尺寸设置")
}
res, err := handler.Client.GetThumbURL(ctx, path, thumbSize[0], thumbSize[1])
if err != nil {
// 如果出现异常就清空文件的pic_info
if file, ok := ctx.Value(fsctx.FileModelCtx).(model.File); ok {
file.UpdatePicInfo("")
}
}
return &response.ContentResponse{
Redirect: true,
URL: res,
}, err
}
// Source 获取外链URL
@@ -63,8 +83,8 @@ func (handler Driver) Token(ctx context.Context, TTL int64, key string) (seriali
return serializer.UploadCredential{}, errors.New("无法获取文件大小")
}
// 如果小于10MB则由服务端中转
if fileSize <= 10*1024*1024 {
// 如果小于4MB则由服务端中转
if fileSize <= SmallFileSize {
return serializer.UploadCredential{}, nil
}

View File

@@ -74,4 +74,9 @@ type BatchResponse struct {
Status int `json:"status"`
}
// ThumbResponse 获取缩略图的响应
type ThumbResponse struct {
Value []map[string]interface{} `json:"value"`
}
var callbackSignal sync.Map

View File

@@ -271,6 +271,8 @@ func GenericAfterUpload(ctx context.Context, fs *FileSystem) error {
// 异步尝试生成缩略图
if fs.User.Policy.IsThumbGenerateNeeded() {
go fs.GenerateThumbnail(ctx, file)
} else if fs.User.Policy.IsMockThumbNeeded() {
file.UpdatePicInfo("1,1")
}
return nil

View File

@@ -31,6 +31,7 @@ func (fs *FileSystem) GetThumb(ctx context.Context, id uint) (*response.ContentR
w, h := fs.GenerateThumbnailSize(0, 0)
ctx = context.WithValue(ctx, fsctx.ThumbSizeCtx, [2]uint{w, h})
ctx = context.WithValue(ctx, fsctx.FileModelCtx, fs.FileTarget[0])
res, err := fs.Handler.Thumb(ctx, fs.FileTarget[0].SourceName)
// TODO 出错时重新生成缩略图