276 lines
7.0 KiB
Go
276 lines
7.0 KiB
Go
|
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
|
||
|
}
|