Golang如何解码Base64并转换为图片保存为随机文件名

Golang如何解码Base64并转换为图片保存为随机文件名 如何解码base64字符串并将其转换为图像,然后以随机字符串作为文件名保存到文件夹中?

7 回复

谢谢,我会去查看的。

更多关于Golang如何解码Base64并转换为图片保存为随机文件名的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


完全没有问题,很高兴能提供帮助。

我今晚会查看一下。如果通过API的POST请求发送base64编码的数据,它会解码并保存吗?

我从文件中读取了经过 base64 编码的字符串,如果你选择从其他地方获取它——当然,这是你的应用程序,做需要做的事情。

base64.StdEncoding.Decode 接收一个字节切片并写入一个字节切片,所以只要你有字节切片——它来自哪里并不重要。

此致。

回复:关于读取、解码和写入的第一部分:

package main

import (
	"encoding/base64"
	"io/ioutil"
)


func main() {
	// read content of the file (base64 encoded)
	encoded, err := ioutil.ReadFile("img.b64")
	if err != nil {
		// check for read error
	}

	// make slice of bytes to store the result
	decoded := make([]byte, base64.StdEncoding.EncodedLen(len(encoded)))

	// decode content of the file into slice of bytes
	_, err = base64.StdEncoding.Decode(decoded, encoded)
	if err != nil {
		// check for decode error
	}

	// write decoded bytes into new file
	err = ioutil.WriteFile("img.png", decoded, 0644)
	if err != nil {
		// check for write error
	}
}

这是我用来测试的 img.b64 文件:https://filebin.net/px5zc5sikjqs8ywo

关于随机字符串文件夹——如果你需要任何帮助,请告诉我,否则编写一个函数或找到现有的函数应该不会太困难。

祝好。

嘿,老兄,你的代码能运行,但我做了一个简单的版本,如下所示:

package main

import (
   b64 "encoding/base64"
   "io/ioutil"
   "time"
   "math/rand"
)


func main() {
  data := "iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAQAAADa613fAAAAaUlEQVR42u3PQREAAAgDINc/9Izg34MGpJ0XIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiJyWYprx532021aAAAAAElFTkSuQmCC"
  sDec, _ := b64.StdEncoding.DecodeString(data)

  rand.Seed(time.Now().UnixNano())
  ioutil.WriteFile( randSeq(12) +".jpg",sDec, 0644)
}

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randSeq(n int) string {
    b := make([]rune, n)
    for i := range b {
        b[i] = letters[rand.Intn(len(letters))]
   }
    return string(b)
}

它将 base64 数据转换并保存为随机命名的图片文件。

在Golang中解码Base64字符串并保存为随机文件名的图片,可以按照以下步骤实现:

package main

import (
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	"os"
	"strings"
)

// 生成随机文件名
func generateRandomFilename(extension string) (string, error) {
	b := make([]byte, 16)
	_, err := rand.Read(b)
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%x%s", b, extension), nil
}

// 解码Base64并保存图片
func saveBase64Image(base64Str, saveDir string) (string, error) {
	// 移除可能的data:image前缀
	parts := strings.SplitN(base64Str, ",", 2)
	if len(parts) == 2 {
		base64Str = parts[1]
	}

	// 解码Base64
	decoded, err := base64.StdEncoding.DecodeString(base64Str)
	if err != nil {
		return "", fmt.Errorf("base64解码失败: %v", err)
	}

	// 检测图片格式并确定扩展名
	extension := determineImageExtension(decoded)
	if extension == "" {
		return "", fmt.Errorf("无法识别的图片格式")
	}

	// 生成随机文件名
	filename, err := generateRandomFilename(extension)
	if err != nil {
		return "", fmt.Errorf("生成文件名失败: %v", err)
	}

	// 确保目录存在
	if err := os.MkdirAll(saveDir, 0755); err != nil {
		return "", fmt.Errorf("创建目录失败: %v", err)
	}

	// 完整文件路径
	filePath := fmt.Sprintf("%s/%s", saveDir, filename)

	// 写入文件
	err = os.WriteFile(filePath, decoded, 0644)
	if err != nil {
		return "", fmt.Errorf("保存文件失败: %v", err)
	}

	return filePath, nil
}

// 根据文件头检测图片格式
func determineImageExtension(data []byte) string {
	if len(data) < 12 {
		return ""
	}

	// 检测常见图片格式
	switch {
	case len(data) > 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF:
		return ".jpg"
	case len(data) > 8 && data[0] == 0x89 && data[1] == 0x50 && data[2] == 0x4E && data[3] == 0x47:
		return ".png"
	case len(data) > 6 && data[0] == 0x47 && data[1] == 0x49 && data[2] == 0x46:
		return ".gif"
	case len(data) > 2 && data[0] == 0x42 && data[1] == 0x4D:
		return ".bmp"
	case len(data) > 12 && data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01 && data[3] == 0x00:
		return ".ico"
	default:
		return ""
	}
}

func main() {
	// 示例Base64字符串(这里用简化的示例,实际使用时替换为完整的Base64字符串)
	base64Image := "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=="
	
	// 保存图片
	savedPath, err := saveBase64Image(base64Image, "./images")
	if err != nil {
		fmt.Printf("保存失败: %v\n", err)
		return
	}
	
	fmt.Printf("图片已保存到: %s\n", savedPath)
}

如果需要处理大文件或需要流式处理,可以使用以下优化版本:

// 流式处理版本
func saveBase64ImageStream(base64Str, saveDir string) (string, error) {
	parts := strings.SplitN(base64Str, ",", 2)
	if len(parts) == 2 {
		base64Str = parts[1]
	}

	// 创建Base64解码器
	decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64Str))

	// 生成随机文件名(先使用临时扩展名)
	filename, err := generateRandomFilename(".tmp")
	if err != nil {
		return "", err
	}

	filePath := fmt.Sprintf("%s/%s", saveDir, filename)
	
	// 确保目录存在
	if err := os.MkdirAll(saveDir, 0755); err != nil {
		return "", err
	}

	// 创建文件
	file, err := os.Create(filePath)
	if err != nil {
		return "", err
	}
	defer file.Close()

	// 复制数据
	_, err = io.Copy(file, decoder)
	if err != nil {
		os.Remove(filePath) // 删除临时文件
		return "", err
	}

	// 重新打开文件读取文件头
	file.Seek(0, 0)
	header := make([]byte, 12)
	_, err = file.Read(header)
	if err != nil {
		os.Remove(filePath)
		return "", err
	}

	// 确定扩展名
	extension := determineImageExtension(header)
	if extension == "" {
		os.Remove(filePath)
		return "", fmt.Errorf("无法识别的图片格式")
	}

	// 重命名为正确的扩展名
	newFilePath := strings.TrimSuffix(filePath, ".tmp") + extension
	err = os.Rename(filePath, newFilePath)
	if err != nil {
		os.Remove(filePath)
		return "", err
	}

	return newFilePath, nil
}

这个实现包含了Base64解码、图片格式检测、随机文件名生成和文件保存的完整流程。determineImageExtension函数通过文件头识别常见的图片格式,确保保存正确的文件扩展名。

回到顶部