Fix: download archived file anonymously

pull/247/head
HFO4 5 years ago
parent 00ef240bea
commit c102c74d6d

@ -27,6 +27,7 @@ type Group struct {
type GroupOption struct { type GroupOption struct {
ArchiveDownloadEnabled bool `json:"archive_download"` ArchiveDownloadEnabled bool `json:"archive_download"`
ArchiveTaskEnabled bool `json:"archive_task"` ArchiveTaskEnabled bool `json:"archive_task"`
OneTimeDownloadEnabled bool `json:"one_time_download"`
} }
// GetAria2Option 获取用户离线下载设备 // GetAria2Option 获取用户离线下载设备

@ -38,13 +38,16 @@ func (fs *FileSystem) Compress(ctx context.Context, folderIDs, fileIDs []uint) (
} }
// 创建临时压缩文件 // 创建临时压缩文件
zipFilePath := filepath.Join(model.GetSettingByName("temp_path"), fmt.Sprintf("archive_%d.zip", time.Now().UnixNano())) zipFilePath := filepath.Join(
model.GetSettingByName("temp_path"),
fmt.Sprintf("archive_%d.zip", time.Now().UnixNano()),
)
zipFile, err := util.CreatNestedFile(zipFilePath) zipFile, err := util.CreatNestedFile(zipFilePath)
defer zipFile.Close()
if err != nil { if err != nil {
util.Log().Warning("%s", err) util.Log().Warning("%s", err)
return "", err return "", err
} }
defer zipFile.Close()
// 创建压缩文件Writer // 创建压缩文件Writer
zipWriter := zip.NewWriter(zipFile) zipWriter := zip.NewWriter(zipFile)

@ -2,7 +2,6 @@ package filesystem
import ( import (
"context" "context"
"errors"
"github.com/HFO4/cloudreve/models" "github.com/HFO4/cloudreve/models"
"github.com/HFO4/cloudreve/pkg/filesystem/local" "github.com/HFO4/cloudreve/pkg/filesystem/local"
"github.com/HFO4/cloudreve/pkg/filesystem/response" "github.com/HFO4/cloudreve/pkg/filesystem/response"
@ -121,10 +120,11 @@ func (fs *FileSystem) dispatchHandler() error {
} }
// NewFileSystemFromContext 从gin.Context创建文件系统 // NewFileSystemFromContext 从gin.Context创建文件系统
// TODO 用户不存在时使用匿名文件系统
func NewFileSystemFromContext(c *gin.Context) (*FileSystem, error) { func NewFileSystemFromContext(c *gin.Context) (*FileSystem, error) {
user, exist := c.Get("user") user, exist := c.Get("user")
if !exist { if !exist {
return nil, errors.New("无法找到用户") return NewAnonymousFileSystem()
} }
fs, err := NewFileSystem(user.(*model.User)) fs, err := NewFileSystem(user.(*model.User))
return fs, err return fs, err

@ -40,6 +40,7 @@ type group struct {
AllowShare bool `json:"allowShare"` AllowShare bool `json:"allowShare"`
AllowRemoteDownload bool `json:"allowRemoteDownload"` AllowRemoteDownload bool `json:"allowRemoteDownload"`
AllowTorrentDownload bool `json:"allowTorrentDownload"` AllowTorrentDownload bool `json:"allowTorrentDownload"`
AllowArchiveDownload bool `json:"allowArchiveDownload"`
} }
type storage struct { type storage struct {
@ -72,6 +73,7 @@ func BuildUser(user model.User) User {
AllowShare: user.Group.ShareEnabled, AllowShare: user.Group.ShareEnabled,
AllowRemoteDownload: aria2Option[0], AllowRemoteDownload: aria2Option[0],
AllowTorrentDownload: aria2Option[2], AllowTorrentDownload: aria2Option[2],
AllowArchiveDownload: user.Group.OptionsSerialized.ArchiveDownloadEnabled,
}, },
} }
} }

@ -4,7 +4,6 @@ import (
"github.com/HFO4/cloudreve/middleware" "github.com/HFO4/cloudreve/middleware"
"github.com/HFO4/cloudreve/pkg/conf" "github.com/HFO4/cloudreve/pkg/conf"
"github.com/HFO4/cloudreve/routers/controllers" "github.com/HFO4/cloudreve/routers/controllers"
"github.com/gin-contrib/cors"
"github.com/gin-contrib/pprof" "github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -19,13 +18,13 @@ func InitRouter() *gin.Engine {
*/ */
r.Use(middleware.Session(conf.SystemConfig.SessionSecret)) r.Use(middleware.Session(conf.SystemConfig.SessionSecret))
// CORS TODO: 根据配置文件来 //// CORS TODO: 根据配置文件来
r.Use(cors.New(cors.Config{ //r.Use(cors.New(cors.Config{
AllowOrigins: []string{"http://localhost:3000"}, // AllowOrigins: []string{"http://localhost:3000"},
AllowMethods: []string{"PUT", "POST", "GET", "OPTIONS"}, // AllowMethods: []string{"PUT", "POST", "GET", "OPTIONS"},
AllowHeaders: []string{"Cookie", "Content-Length", "Content-Type", "X-Path", "X-FileName"}, // AllowHeaders: []string{"Cookie", "Content-Length", "Content-Type", "X-Path", "X-FileName"},
AllowCredentials: true, // AllowCredentials: true,
})) //}))
// 测试模式加入Mock助手中间件 // 测试模式加入Mock助手中间件
if gin.Mode() == gin.TestMode { if gin.Mode() == gin.TestMode {
@ -67,8 +66,10 @@ func InitRouter() *gin.Engine {
{ {
file := sign.Group("file") file := sign.Group("file")
{ {
// 下載文件 // 文件外链
file.GET("get/:id/:name", controllers.AnonymousGetContent) file.GET("get/:id/:name", controllers.AnonymousGetContent)
// 下載已经打包好的文件
file.GET("archive/:id/archive.zip", controllers.DownloadArchive)
} }
} }
@ -104,8 +105,6 @@ func InitRouter() *gin.Engine {
file.GET("source/:id", controllers.GetSource) file.GET("source/:id", controllers.GetSource)
// 打包要下载的文件 // 打包要下载的文件
file.POST("archive", controllers.Archive) file.POST("archive", controllers.Archive)
// 下載已经打包好的文件
file.Use(middleware.SignRequired()).GET("archive/:id", controllers.DownloadArchive)
} }
// 目录 // 目录

@ -6,11 +6,9 @@ import (
"github.com/HFO4/cloudreve/pkg/filesystem" "github.com/HFO4/cloudreve/pkg/filesystem"
"github.com/HFO4/cloudreve/pkg/filesystem/fsctx" "github.com/HFO4/cloudreve/pkg/filesystem/fsctx"
"github.com/HFO4/cloudreve/pkg/serializer" "github.com/HFO4/cloudreve/pkg/serializer"
"github.com/HFO4/cloudreve/pkg/util"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"io" "io"
"net/http" "net/http"
"os"
"time" "time"
) )
@ -48,21 +46,20 @@ func (service *ArchiveDownloadService) Download(ctx context.Context, c *gin.Cont
return serializer.Err(serializer.CodeNotSet, err.Error(), err) return serializer.Err(serializer.CodeNotSet, err.Error(), err)
} }
if fs.User.Group.OptionsSerialized.OneTimeDownloadEnabled {
// 清理资源,删除临时文件
_ = cache.Deletes([]string{service.ID}, "archive_")
}
c.Header("Content-Disposition", "attachment;")
c.Header("Content-Type", "application/zip") c.Header("Content-Type", "application/zip")
http.ServeContent(c.Writer, c.Request, "archive.zip", time.Now(), rs) http.ServeContent(c.Writer, c.Request, "", time.Now(), rs)
// 检查是否需要关闭文件 // 检查是否需要关闭文件
if fc, ok := rs.(io.Closer); ok { if fc, ok := rs.(io.Closer); ok {
err = fc.Close() err = fc.Close()
} }
// 清理资源,删除临时文件
_ = cache.Deletes([]string{service.ID}, "archive_")
err = os.Remove(zipPath.(string))
if err != nil {
util.Log().Warning("无法删除临时文件 %s %s", zipPath, err)
}
return serializer.Response{ return serializer.Response{
Code: 0, Code: 0,
} }

@ -61,13 +61,13 @@ func (service *ItemService) Archive(ctx context.Context, c *gin.Context) seriali
} }
zipID := util.RandStringRunes(16) zipID := util.RandStringRunes(16)
signedURI, err := auth.SignURI( signedURI, err := auth.SignURI(
fmt.Sprintf("/api/v3/file/archive/%s", zipID), fmt.Sprintf("/api/v3/file/archive/%s/archive.zip", zipID),
time.Now().Unix()+120, time.Now().Unix()+30,
) )
finalURL := siteURL.ResolveReference(signedURI).String() finalURL := siteURL.ResolveReference(signedURI).String()
// 将压缩文件记录存入缓存 // 将压缩文件记录存入缓存
err = cache.Set("archive_"+zipID, zipFile, 120) err = cache.Set("archive_"+zipID, zipFile, 30)
if err != nil { if err != nil {
return serializer.Err(serializer.CodeIOFailed, "无法写入缓存", err) return serializer.Err(serializer.CodeIOFailed, "无法写入缓存", err)
} }

Loading…
Cancel
Save