2017-09-03 104 views
2

我收到圖像爲base64字符串(dataurl),下面是我的函數的dataurl轉換成圖像,隱蔽的base64字符串JPG Golang

現在,如果圖像比爲png庫將創建爲PNG圖像和jpg庫會拋出錯誤,反之亦然。

問題是,當我上傳png格式它工作得很好,但是當我上傳JPG文件
返回該錯誤

無效的JPEG格式:缺少SOI標記

func (ProfileController) SetProfilePic(w http.ResponseWriter, r *http.Request) { 

    session, _ := session.UserSession.Get(r, "mvc-user-session") 

    var fieldMapForBasic map[string]*json.RawMessage 
    var f *os.File 

    data, _ := ioutil.ReadAll(r.Body) 
    json.Unmarshal(data, &fieldMapForBasic) 

    image, _ := json.Marshal(fieldMapForBasic["image"]) 
    coI := strings.Index(string(image), ",") 
    rawImage := string(image)[coI+1:] 

    // Encoded Image DataUrl // 
    unbased, _ := base64.StdEncoding.DecodeString(string(rawImage)) 

    res := bytes.NewReader(unbased) 
    path , _ := os.Getwd() 


    // Path to store the image // 
    newpath := filepath.Join(path + "/storage", strconv.Itoa(session.Values["id"].(int))) 
    os.MkdirAll(newpath, os.ModePerm) 
    uid := uuid.NewV4() 
    fmt.Println(newpath) 

    // if image is png this function will create the image from dataurl string// 
    pngI, errPng := png.Decode(res) 
    if errPng == nil { 
     f, _ = os.OpenFile(newpath + "/" + uid.String() + ".png", os.O_WRONLY | os.O_CREATE, 0777) 
     png.Encode(f, pngI) 
     fmt.Println("Png generated") 
     user := model.User{} 
     user.ProfilePic = "storage/"+ strconv.Itoa(session.Values["id"].(int)) + "/" + uid.String() 
     session.Values["profile_pic"] = user.ProfilePic 
     session.Save(r,w) 
     database.Connection.Id(session.Values["id"].(int)).Update(&user) 
    }else{ 
     fmt.Println(errPng.Error()) 
    } 


    // If image is Jpg this will generate the Image // 
    jpgI, errJpg := jpeg.Decode(res) 
    if errJpg == nil { 
     f, _ = os.OpenFile(newpath + "/" + uid.String() + ".jpg", os.O_WRONLY | os.O_CREATE, 0777) 
     jpeg.Encode(f, jpgI, &jpeg.Options{Quality:75}) 
     fmt.Println("Jpg created") 
    }else { 
     fmt.Println(errJpg.Error()) 
    } 


    defer func() { 
     f.Close() 
    }() 


    render.Json(w, "ok") 
} 

輸入dataurl是:

「的數據:圖像/ JPEG; BASE64,/ 9J/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAM FBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCADeAN4DASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4 + Tl5ufo6erx8vP09fb3 + PN6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3 + PN6/9oADAMBAAIRAxEAPwDtKKKK/cD8rCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACi iigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/Z」

這可能有助於

+2

我不知道是什麼「SOI錯誤」的意思是,但你試圖解碼與PNG和JPEG相同的數據(存儲在「res」中)。 – Carpetsmoker

+0

我已更新問題 – mchampaneri

回答

2

您正在將io.Reader傳遞給png.Decode(),這會開始消費讀者,只會發現輸入不是有效的PNG,因此會返回錯誤。

然後將您部分使用的閱讀器傳遞給jpeg.Decode(),該閱讀器讀取尚未讀取的數據,該數據不是有效的JPEG,並返回您觀察到的錯誤。

你需要爲每個解碼器創建一個新的讀者:

pngI, errPng := png.Decode(bytes.NewReader(unbased)) 

// ... 

jpgI, errJpg := jpeg.Decode(bytes.NewReader(unbased)) 

或者更好的是,考慮MIME類型,只調用合適的解碼器:

switch strings.TrimSuffix(image[5:coI], ";base64") { 
case "image/png": 
    pngI, err = png.Decode(res) 
    // ... 
case "image/jpeg": 
    jpgI, err = jpeg.Decode(res) 
    // ... 
} 
+0

這工作。但如果你能解釋更多一點,這將是可觀的。我是golang的初學者。 – mchampaneri

+0

你想讓我進一步解釋什麼? – Flimzy

+0

「部分消耗的閱讀器傳遞給jpeg.Decode()」。我無法理解這一點。我通過了對於新讀者來說相同的資源。不是嗎? – mchampaneri

2

這裏的東西可以幫助演示了其他不少東西太(你需要有兩個文件:爲Flower.jpg和mouse.png,使這項工作,可以在倉庫https://github.com/rravishankar/golangtraining/tree/master/test/jpegencode):

package main 

import (
    "bufio" 
    "encoding/base64" 
    "fmt" 
    "image" 
    "image/jpeg" 
    "image/png" 
    "strings" 

    "log" 
    "os" 
) 

func main() { 

    createJpg() 
    createPng() 
    base64toPng() 
    base64toJpg(getJPEGbase64("flower.jpg")) 
} 

//Take an existing jpg srcFileName and decode/encode it 
func createJpg() { 

    srcFileName := "flower.jpg" 
    dstFileName := "newFlower.jpg" 
    // Decode the JPEG data. If reading from file, create a reader with 
    reader, err := os.Open(srcFileName) 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer reader.Close() 
    //Decode from reader to image format 
    m, formatString, err := image.Decode(reader) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 
    fmt.Println("Got format String", formatString) 
    fmt.Println(m.Bounds()) 

    //Encode from image format to writer 
    f, err := os.OpenFile(dstFileName, os.O_WRONLY|os.O_CREATE, 0777) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 

    err = jpeg.Encode(f, m, &jpeg.Options{Quality: 75}) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 
    fmt.Println("Jpg file", dstFileName, "created") 

} 

//Take an existing png srcFileName and decode/encode it 
func createPng() { 
    srcFileName := "mouse.png" 
    dstFileName := "newMouse.png" 
    reader, err := os.Open(srcFileName) 
    if err != nil { 
     log.Fatal(err) 
    } 
    defer reader.Close() 
    //Decode from reader to image format 
    m, formatString, err := image.Decode(reader) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 
    fmt.Println("Got format String", formatString) 
    fmt.Println(m.Bounds()) 

    //Encode from image format to writer 
    f, err := os.OpenFile(dstFileName, os.O_WRONLY|os.O_CREATE, 0777) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 

    err = png.Encode(f, m) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 
    fmt.Println("Png file", dstFileName, "created") 

} 

//Converts pre-existing base64 data (found in example of https://golang.org/pkg/image/#Decode) to test.png 
func base64toPng() { 
    const data = ` 
/9j/4AAQSkZJRgABAQIAHAAcAAD/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdA 
SFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2Nj 
Y2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wAARCABnAJYDASIAAhEBAxEB/8QA 
HwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIh 
MUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVW 
V1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG 
x8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQF 
BgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV 
YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE 
hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq 
8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDlwKMD0pwzSiuK57QzGDxS7D6in8Y5ximnAPUfSlcq4m3ilUYp 
2OKXHvRcVxnTtS7c07HNFK4DQPakC4PNOA+tOx70XAjK/So5gBGP94fzqfvUVx/qxx/EP51UXqRP4WSE 
cmgjilP3jSEZqS0IO/NGDnpUiocDg/McDjvV6HTPOdVWYgsM5KcfzzQ2JySM2jp6VYu7SWzmMUwG4cgj 
kMPUVBjjtTGtRu0Zopw+lFFxhinrGzuqqMsxAA9yaXFSRv5cqSEcIwYj6GpuZ30O30fSLKzhUpbpNMv3 
5XGTn29BV28jt7pPLuIVljPBBFVreYx+VbqAjycgt3x14zRcNOxGyVFHQkIc/wA61exyKLbuzjdZ046d 
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 
` 

    reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data)) 
    m, formatString, err := image.Decode(reader) 
    if err != nil { 
     log.Fatal(err) 
    } 
    bounds := m.Bounds() 
    fmt.Println(bounds, formatString) 

    //Encode from image format to writer 
    pngFilename := "test.png" 
    f, err := os.OpenFile(pngFilename, os.O_WRONLY|os.O_CREATE, 0777) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 

    err = png.Encode(f, m) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 
    fmt.Println("Png file", pngFilename, "created") 

} 

//Given a base64 string of a JPEG, encodes it into an JPEG image test.jpg 
func base64toJpg(data string) { 

    reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data)) 
    m, formatString, err := image.Decode(reader) 
    if err != nil { 
     log.Fatal(err) 
    } 
    bounds := m.Bounds() 
    fmt.Println("base64toJpg", bounds, formatString) 

    //Encode from image format to writer 
    pngFilename := "test.jpg" 
    f, err := os.OpenFile(pngFilename, os.O_WRONLY|os.O_CREATE, 0777) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 

    err = jpeg.Encode(f, m, &jpeg.Options{Quality: 75}) 
    if err != nil { 
     log.Fatal(err) 
     return 
    } 
    fmt.Println("Jpg file", pngFilename, "created") 

} 

//Gets base64 string of an existing JPEG file 
func getJPEGbase64(fileName string) string { 

    imgFile, err := os.Open(fileName) 

    if err != nil { 
     fmt.Println(err) 
     os.Exit(1) 
    } 

    defer imgFile.Close() 

    // create a new buffer base on file size 
    fInfo, _ := imgFile.Stat() 
    var size = fInfo.Size() 
    buf := make([]byte, size) 

    // read file content into buffer 
    fReader := bufio.NewReader(imgFile) 
    fReader.Read(buf) 

    imgBase64Str := base64.StdEncoding.EncodeToString(buf) 
    //fmt.Println("Base64 string is:", imgBase64Str) 
    return imgBase64Str 

} 

您可能還想閱讀https://golang.org/pkg/image/#Decode 中的示例希望這有助於您。

+0

這是我的Jpg輸入字符串 – mchampaneri

+0

如果缺少SOI標記,那麼base64字符串中可能缺少一些字節(https://en.wikipedia.org/wiki/JPEG_File_Interchange_Format#File_format_structure)修改您的程序打印JPEG的base64字符串。然後使用您的JPEG base64字符串作爲輸入(對'base64toJpg'函數)分別運行我的程序(演示工作) - 查看您是否獲得了JPEG。如果出現錯誤,請查看它是什麼,如果需要,請獲取源JPEG,使用上述代碼中的getJPEGbase64函數獲取base64字符串,並匹配您在http請求中獲得的base64字符串。 – Ravi

+0

我已經測試了base64字符串在線https://codebeautify.org/base64-to-image-converter。它工作正常 – mchampaneri