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 }