首页 > 解决方案 > 在 Go 中获取文件的内容类型时遇到问题

问题描述

我有一个函数,我在其中接收一个 base64 字符串并获取它的内容(PDF 或 JPEG)。我读入 base64 内容,将其转换为字节并将其解码为文件。然后我创建一个文件,我将在其中输出解码后的文件(JPEG 或 PDF)。然后我将字节写入它。然后我在它上面调用我的 GetFileContentType,它返回给我一个空字符串。如果我单独运行这些函数,就像我首先创建解码文件的第一个函数一样,然后结束它。然后调用第二个函数来获取内容类型,它可以工作并将其返回为 JPEG 或 PDF。我在这里做错了什么?有没有更好的方法来做到这一点?

func ConvertToJPEGBase64(
    src string,
    dst string,
) error {

    b, err := ioutil.ReadFile(src)
    if err != nil {
        return err
    }
    str := string(b)

    byteArray, err := base64.StdEncoding.DecodeString(str)
    if err != nil {
        return err
    }

    f, err := os.Create(dst)
    if err != nil {
        return err
    }

    if _, err := f.Write(byteArray); err != nil {
        return err
    }

    f.Sync()
    filetype, err := client.GetFileContentType(f)
    if err != nil {
        return err
    }
    if strings.Contains(filetype, "jpeg") {
             // do something
    } else {
            // do something else
    }

    return nil
}

// GetFileContentType tells us the type of file
func GetFileContentType(out *os.File) (string, error) {

    // Only the first 512 bytes are used to sniff the content type.
    buffer := make([]byte, 512)
    _, err := out.Read(buffer)
    if err != nil {
        return "", err
    }
    contentType := http.DetectContentType(buffer)

    return contentType, nil
}

标签: go

解决方案


问题是GetFileContentType从文件末尾读取。在调用调用之前修复此问题GetFileContentType

 if _, err := f.Seek(io.SeekStart, 0); err != nil {
     return err
 }

更好的解决方法是使用已经在内存中的文件数据。这将代码简化到不需要GetFileContentType函数的程度。

func ConvertToJPEGBase64(
    src string,
    dst string,
) error {

    b, err := ioutil.ReadFile(src)
    if err != nil {
        return err
    }
    str := string(b)

    byteArray, err := base64.StdEncoding.DecodeString(str)
    if err != nil {
        return err
    }

    f, err := os.Create(dst)
    if err != nil {
        return err
    }
    defer f.Close() // <-- Close the file on return.

    if _, err := f.Write(byteArray); err != nil {
        return err
    }

    fileType := http.DetectContentType(byteArray) // <-- use data in memory
    if strings.Contains(fileType, "jpeg") {
             // do something
    } else {
            // do something else
    }

    return nil
}

可以使用以下方法消除更多代码ioutil.WriteFile

func ConvertToJPEGBase64(src, dst string) error {
    b, err := ioutil.ReadFile(src)
    if err != nil {
        return err
    }

    byteArray, err := base64.StdEncoding.DecodeString(string(b))
    if err != nil {
        return err
    }

    if err := ioutil.WriteFile(dst, byteArray, 0666); err != nil {
        return err
    }

    fileType := http.DetectContentType(byteArray)
    if strings.Contains(fileType, "jpeg") {
        // do something
    } else {
        // do something else
    }

    return nil
}

推荐阅读