1.1. 前言

需要批量上传图片到图床,之前用python写脚本倒是很简单,不过GO因为并发太强大了,所以这次用GO来试试

1.2. 基础版

构建一个上传图片的请求,主要代码在imgkr()函数中

package main

import (
    "bytes"
    "fmt"
    "golang.org/x/net/publicsuffix"
    "io"
    "math/rand"
    "mime/multipart"
    "net/http"
    "net/http/cookiejar"
    "os"
    "path/filepath"
)

var client http.Client

func imgkr() {
    // 要上传的文件
    imgFilePath := "/Users/d4m1ts/d4m1ts/Upload/logo.png"
    file, _ := os.Open(imgFilePath)
    defer file.Close()

    // 设置body数据并写入缓冲区
    bodyBuff := bytes.NewBufferString("") //bodyBuff := &bytes.Buffer{}
    bodyWriter := multipart.NewWriter(bodyBuff)
    _ = bodyWriter.SetBoundary(fmt.Sprintf("-----------------------------%d", rand.Int()))
    // 加入图片二进制
    part, _ := bodyWriter.CreateFormFile("source", filepath.Base(file.Name()))
    _, _ = io.Copy(part, file)
    // 其他字段
    _ = bodyWriter.WriteField("a", "b")

    // 自动补充boundary结尾
    bodyWriter.Close()

    fmt.Println(bodyBuff) //构建的完整数据包,没有header

    // 组合创建数据包
    req, _ := http.NewRequest("POST", "http://127.0.0.1:8000", bodyBuff)
    req.ContentLength = int64(bodyBuff.Len())
    req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0")

    client.Do(req)
}


func main() {
    jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
    client = http.Client{Jar: jar}
    imgkr()
}

接收到的数据包

image-20220121124500395

1.3. 进阶版

上面的数据包大概是没什么问题,但是图片的Content-Typeapplication/octet-stream,而一般情况下图片的应该是形如image/png

分析了一下原因,是因为CreateFormFile函数里面硬编码了

image-20220121124642839

看里面的一些函数,也没找到直接设置这个地方的Content-Type的,所以我决定根据他的规则重新写一下。


分析这个函数,前面h是header头,也是我们要修改的地方,后面是调用*Writer.CreatePart,我们也模拟这个行为就可以了

所以微调一下代码(直接给代码复制粘贴过来改就可以了,也可以直接重写CreateFormFile函数,后者稍微麻烦一点点)

image-20220121125248539

效果

image-20220121125505840

目标达成,完整代码

package main

import (
    "bytes"
    "fmt"
    "golang.org/x/net/publicsuffix"
    "io"
    "math/rand"
    "mime/multipart"
    "net/http"
    "net/http/cookiejar"
    "net/textproto"
    "os"
    "path/filepath"
    "strings"
)

var client http.Client
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func escapeQuotes(s string) string {
    return quoteEscaper.Replace(s)
}

func imgkr() {
    // 要上传的文件
    imgFilePath := "/Users/d4m1ts/d4m1ts/Upload/logo.png"
    file, _ := os.Open(imgFilePath)
    defer file.Close()

    // 设置body数据并写入缓冲区
    bodyBuff := bytes.NewBufferString("") //bodyBuff := &bytes.Buffer{}
    bodyWriter := multipart.NewWriter(bodyBuff)
    _ = bodyWriter.SetBoundary(fmt.Sprintf("-----------------------------%d", rand.Int()))
    // 加入图片二进制
    h := make(textproto.MIMEHeader)
    h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, escapeQuotes("source"), escapeQuotes(filepath.Base(file.Name()))))
    h.Set("Content-Type", "image/png")
    part, _ := bodyWriter.CreatePart(h)
    _, _ = io.Copy(part, file)
    // 其他字段
    _ = bodyWriter.WriteField("a", "b")

    // 自动补充boundary结尾
    bodyWriter.Close()

    fmt.Println(bodyBuff) //构建的完整数据包,没有header

    // 组合创建数据包
    req, _ := http.NewRequest("POST", "http://127.0.0.1:8000", bodyBuff)
    req.ContentLength = int64(bodyBuff.Len())
    req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0")

    client.Do(req)
}


func main() {
    jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
    client = http.Client{Jar: jar}
    imgkr()
}

1.4. 完整版

写了一个上传到https://imgtu.com/的,大家有需可以参考

为了方便以后的复制粘贴,给构造上传图片请求单独写到imgkr()函数中的,不然应该给结果解析也写里面的

package main

import (
    "bytes"
    "fmt"
    "golang.org/x/net/publicsuffix"
    "io"
    "io/ioutil"
    "math/rand"
    "mime/multipart"
    "net/http"
    "net/http/cookiejar"
    "net/textproto"
    "os"
    "path/filepath"
    "regexp"
    "strings"
    "time"
    "github.com/json-iterator/go"
)

var client http.Client
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")

func escapeQuotes(s string) string {
    return quoteEscaper.Replace(s)
}

/*
获取上传图片需要的token
 */
func getToken() string {
    u := "https://imgtu.com/"
    req, _ := http.NewRequest("GET", u, nil)
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0")
    resp, _ := client.Do(req)
    res,_ := ioutil.ReadAll(resp.Body)
    regex, _ := regexp.Compile("PF.obj.config.auth_token = \"(.*?)\";")
    if regex.MatchString(string(res)){
        token := regex.FindStringSubmatch(string(res))[1]
        return token
    }
    return ""

}

/*
构造上传请求
 */
func imgkr(token string, imgFilePath string) *http.Request {
    // 上传网址
    target := "https://imgtu.com/json"
    // 要上传的文件
    file, _ := os.Open(imgFilePath)
    defer file.Close()

    // 设置body数据并写入缓冲区
    bodyBuff := bytes.NewBufferString("") //bodyBuff := &bytes.Buffer{}
    bodyWriter := multipart.NewWriter(bodyBuff)
    _ = bodyWriter.SetBoundary(fmt.Sprintf("-----------------------------%d", rand.Int()))
    // 加入图片二进制
    h := make(textproto.MIMEHeader)
    h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, escapeQuotes("source"), escapeQuotes(filepath.Base(file.Name()))))
    h.Set("Content-Type", "image/png")
    part, _ := bodyWriter.CreatePart(h)
    _, _ = io.Copy(part, file)
    // 其他字段
    _ = bodyWriter.WriteField("type", "file")
    _ = bodyWriter.WriteField("action", "upload")
    _ = bodyWriter.WriteField("timestamp", fmt.Sprintf("%d", time.Now().UnixNano()/1e6))
    _ = bodyWriter.WriteField("auth_token", token)
    _ = bodyWriter.WriteField("nsfw", "0")
    // 自动补充boundary结尾
    _ = bodyWriter.Close()

    //fmt.Println(bodyBuff) //构建的完整数据包,没有header

    // 创建请求
    req, _ := http.NewRequest("POST", target, bodyBuff)
    req.ContentLength = int64(bodyBuff.Len())
    req.Header.Set("Content-Type", bodyWriter.FormDataContentType())
    req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0")

    return req
}


func main() {
    jar, _ := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
    client = http.Client{Jar: jar}

    token := getToken()
    req := imgkr(token, "/Users/d4m1ts/d4m1ts/Upload/logo.png")

    resp, _ := client.Do(req)
    res, _ := ioutil.ReadAll(resp.Body)
    imageUrl := jsoniter.Get(res, "image").Get("url")
    fmt.Println(imageUrl.ToString())
}

效果

image-20220121134709904

Copyright © d4m1ts 2022 all right reserved,powered by Gitbook该文章修订时间: 2022-01-21 13:53:00

results matching ""

    No results matching ""