ifms_go/test/oss_test.go

276 lines
7.0 KiB
Go
Raw Permalink Normal View History

2025-06-10 17:50:46 +08:00
package test
import (
"archive/zip"
"context"
"fmt"
"github.com/gin-gonic/gin"
"github.com/skip2/go-qrcode"
"ifms/internal/config"
"ifms/pkg/oss"
"io"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"testing"
"time"
)
// 上传阿里云OSS文件
func TestOssPut(t *testing.T) {
// 使用全局客户端上传文件
ctx := context.Background()
file, err := os.Open("/Users/shaolingjin/source/qk/ifms/test/1748931313350.jpg")
if err != nil {
fmt.Println("Failed to open file:", err)
return
}
defer file.Close()
//获取文件大小
fileInfo, err := file.Stat()
if err != nil {
fmt.Println("Failed to get file size:", err)
return
}
fileSize := fileInfo.Size()
name := oss.FormatObjectName("test/test1", "1748931313350.jpg")
result, err := oss.Ins.PutObject(ctx, "qkkj-ifms-test", name, file, fileSize, oss.PutObjectOptions{
ContentType: "image/jpeg",
})
if err != nil {
fmt.Println("Failed to upload object:", err)
return
}
fmt.Println(result)
// 使用表单上传文件 c *gin.Context
//img, err := c.FormFile("file")
// if err != nil {
// logger.Error("图片上传失败,", u.Username, ":", err)
// ResFail(c, "图片上传失败")
// return
// }
// if img == nil {
// ResFail(c, "请选择图片上传")
// return
// }
// img_width := DEFAULT_IMG_WIDTH
// fn := fmt.Sprintf("%s/%s", "./img", img.Filename)
// fileExt := path.Ext(fn)
// filename := fmt.Sprintf("%s/%s/%d%s", PATH_AISHOP_IMG, u.Username, time.Now().Unix(), fileExt)
// err = c.SaveUploadedFile(img, filename)
// if err != nil {
// logger.Error("图片保存失败,", u.Username, ":", err)
// ResFail(c, "图片上传失败")
// return
// }
}
// 获取阿里云OSS文件
func TestOssGet(t *testing.T) {
// 使用全局客户端上传文件
ctx := context.Background()
//name := oss.FormatObjectName("test", "example.txt")
objName := "trace/code/1749526273.png"
object, err := oss.Ins.GetObject(ctx, config.C.AliyunOSS.Bucket, objName)
if err != nil {
fmt.Println("Failed to get object:", err)
return
}
defer object.Close()
data, err := ioutil.ReadAll(object)
if err != nil {
fmt.Println(err)
}
fmt.Println("size of data is: ", data)
}
func TestQrCode(t *testing.T) {
baseURL := "http://118.178.59.140:8040/api/v1/trace/code/"
params := url.Values{}
params.Add("breeding_batch", "25年黄辣丁052702批")
params.Add("ho_id", "1")
// 拼接完整的 URL
fullURL := baseURL + "?" + params.Encode()
qr, err := qrcode.New(fullURL, qrcode.Medium)
if err != nil {
log.Fatalf("An error occurred: %v", err)
}
if _, err := os.Stat("./qrcode"); os.IsNotExist(err) {
// 创建目录
err = os.MkdirAll("./qrcode", 0755) // 0755 表示权限
}
// 保存为PNG文件
f := fmt.Sprintf("%d.png", time.Now().Unix())
err = qr.WriteFile(256, "./qrcode/"+f) // 第二个参数是图片的分辨率,可以根据需要调整
if err != nil {
log.Fatalf("An error occurred while writing the QR code to file: %v", err)
}
ctx := context.Background()
file, err := os.Open("./qrcode/" + f)
if err != nil {
log.Fatalf("%v", err)
}
stat, err := file.Stat()
if err != nil {
log.Fatalf("%v", err)
}
// 上传到阿里云
name := oss.FormatObjectName("trace/code", f)
ossResult, err := oss.Ins.PutObject(ctx, config.C.AliyunOSS.Bucket, name, file, stat.Size())
if err != nil {
log.Fatalf("%v", err)
}
fmt.Println(ossResult.URL)
}
// 下载对象结构体
type DownloadObject struct {
ObjName string `json:"objName"` // OSS 对象名称
FileName string `json:"fileName"` // 本地保存的文件名
}
// 下载接口
func DownloadFilesFromOSS(c *gin.Context) {
// 解析前端传入的 JSON 数据
var downloadObjs []DownloadObject
downloadObjs = append(downloadObjs, DownloadObject{
ObjName: "trace/code/1749526273.png",
FileName: "downloaded_image.png",
})
// 创建下载目录 ./trace/download/
downloadDir := "./trace/download/"
if err := os.MkdirAll(downloadDir, 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建下载目录失败"})
return
}
// 获取当前时间戳作为子目录名
timestamp := time.Now().Unix()
timestampDir := filepath.Join(downloadDir, fmt.Sprintf("%d", timestamp))
if err := os.MkdirAll(timestampDir, 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建时间戳目录失败"})
return
}
ctx := context.Background()
// 下载文件到时间戳目录并重命名
for _, obj := range downloadObjs {
// OSS 对象名称
objectName := obj.ObjName
// 本地保存的完整路径
localPath := filepath.Join(timestampDir, obj.FileName)
// 下载文件
object, err := oss.Ins.GetObject(ctx, config.C.AliyunOSS.Bucket, objectName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("下载文件 %s 失败: %v", objectName, err)})
return
}
defer object.Close()
file, err := os.Create(localPath)
if err != nil {
fmt.Printf("Failed to create file: %v\n", err)
return
}
defer file.Close()
// 将数据从 OSS 对象流式写入本地文件
_, err = io.Copy(file, object)
if err != nil {
fmt.Printf("Failed to write file: %v\n", err)
return
}
}
// 压缩时间戳目录下的所有文件到 ZIP 文件
zipFilePath := filepath.Join(downloadDir, fmt.Sprintf("%d.zip", timestamp))
if err := zipDirectory(timestampDir, zipFilePath); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "压缩文件失败"})
return
}
// 将 ZIP 文件提供给前端下载
c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s.zip", timestamp))
c.Header("Content-Transfer-Encoding", "binary")
// 读取 ZIP 文件并发送到响应体
file, err := os.Open(zipFilePath)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "打开 ZIP 文件失败"})
return
}
defer file.Close()
// 流式传输 ZIP 文件内容
_, err = io.Copy(c.Writer, file)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "传输文件失败"})
return
}
// 删除临时文件和目录
os.Remove(zipFilePath)
os.RemoveAll(timestampDir)
c.Status(http.StatusOK)
}
// 压缩目录到 ZIP 文件
func zipDirectory(srcDir, zipFile string) error {
zipWriter, err := os.Create(zipFile)
if err != nil {
return fmt.Errorf("创建 ZIP 文件失败: %v", err)
}
defer zipWriter.Close()
archive := zip.NewWriter(zipWriter)
defer archive.Close()
// 递归添加目录中的文件到 ZIP
err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// 跳过目录本身
if info.IsDir() {
return nil
}
// 获取文件相对于 srcDir 的路径
filePath, err := filepath.Rel(srcDir, path)
if err != nil {
return err
}
// 添加文件到 ZIP
writer, err := archive.Create(filePath)
if err != nil {
return err
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
return err
}