feat: 添加下载文件到浏览器功能

This commit is contained in:
2026-04-22 12:49:27 +08:00
parent 98f0082d44
commit 3055b15855
4 changed files with 74 additions and 0 deletions

View File

@@ -22,6 +22,12 @@ func (c *file) DownloadToFile(ctx context.Context, req *dto.DownloadToFileReq) (
return
}
// DownloadToBrowser 下载文件到浏览器
func (c *file) DownloadToBrowser(ctx context.Context, req *dto.DownloadToBrowserReq) (res *beans.ResponseEmpty, err error) {
err = service.File.DownloadToBrowser(ctx, req)
return
}
// UploadFile 上传文件
func (c *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto.UploadFileRes, err error) {
return service.File.UploadFile(ctx, req)

View File

@@ -5,6 +5,7 @@ import (
"context"
"encoding/base64"
"fmt"
"io"
"net/http"
"path/filepath"
"strings"
@@ -223,3 +224,45 @@ func DownloadToFile(ctx context.Context, fileURL string, localPath string) (err
return
}
// DownloadToBrowser 下载文件到浏览器(返回文件流,由 HTTP Response 直接写出)
// 参数 fileURL: MinIO 中的对象路径(即 objectName
// 返回: 文件字节流、文件名、ContentType、错误
func DownloadToBrowser(ctx context.Context, fileURL string) (fileBytes []byte, fileName string, contentType string, err error) {
bucketName, err := utils.GetBucketName(ctx)
if err != nil {
glog.Errorf(ctx, "获取桶名称失败: %v", err)
return
}
// 获取对象流
object, err := minioClient.GetObject(ctx, bucketName, fileURL, minio.GetObjectOptions{})
if err != nil {
glog.Errorf(ctx, "获取文件流失败: %v", err)
return
}
defer object.Close()
// 获取对象元信息(用于读取 ContentType 和 Size
info, err := object.Stat()
if err != nil {
glog.Errorf(ctx, "获取文件信息失败: %v", err)
return
}
// 读取全部内容
fileBytes, err = io.ReadAll(object)
if err != nil {
glog.Errorf(ctx, "读取文件流失败: %v", err)
return
}
// 提取文件名
fileName = filepath.Base(fileURL)
contentType = info.ContentType
if contentType == "" {
contentType = "application/octet-stream"
}
return
}

View File

@@ -11,6 +11,12 @@ type DownloadToFileReq struct {
LocalPath string `json:"localPath" dc:"本地路径"`
}
// DownloadToBrowserReq 下载文件到浏览器请求
type DownloadToBrowserReq struct {
g.Meta `path:"/downloadToBrowser" method:"post" tags:"存储管理" summary:"下载文件到浏览器" dc:"下载文件到浏览器"`
FileURL string `json:"fileURL" dc:"文件URL" in:"query"`
}
// UploadFileReq 上传文件请求
type UploadFileReq struct {
g.Meta `path:"/uploadFile" method:"post" tags:"存储管理" summary:"上传文件" dc:"上传文件"`

View File

@@ -3,6 +3,7 @@ package service
import (
"context"
"fmt"
"net/url"
"oss/consts"
"oss/dao"
"oss/minio"
@@ -10,6 +11,7 @@ import (
"oss/model/entity"
"time"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/glog"
"gitea.com/red-future/common/utils"
@@ -27,6 +29,23 @@ func (f *file) DownloadToFile(ctx context.Context, req *dto.DownloadToFileReq) (
return minio.DownloadToFile(ctx, req.FileURL, req.LocalPath)
}
// DownloadToBrowser 下载文件到浏览器
func (f *file) DownloadToBrowser(ctx context.Context, req *dto.DownloadToBrowserReq) (err error) {
fileBytes, fileName, contentType, err := minio.DownloadToBrowser(ctx, req.FileURL)
if err != nil {
return err
}
r := ghttp.RequestFromCtx(ctx)
// 设置响应头
r.Response.Header().Set("Content-Type", contentType)
r.Response.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"; filename*=UTF-8''%s`, fileName, url.PathEscape(fileName)))
r.Response.Header().Set("Content-Length", fmt.Sprintf("%d", len(fileBytes)))
// 写出二进制流
r.Response.Write(fileBytes)
return
}
func (f *file) UploadFile(ctx context.Context, req *dto.UploadFileReq) (res *dto.UploadFileRes, err error) {
fileSize := gconv.Int(req.File.Size)
totalFileSize := 0