golang模拟web上传

realizationmecha · · 2419 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

最近都在学习golang的内容,今天写了点东西。

学习是基于网上的一些文章。不过功能是全新的

1)实现golang请求Get

2)实现post登陆

3) 实现web上传(基于pp.sohu.com)

代码实现:

package main

import (
	"base"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"regexp"
	"strings"
)

var gCurCookies []*http.Cookie
var gCurCookieJar *cookiejar.Jar
var logger *log.Logger

/*UploadBodyEle struct
--ad36e31ab0e27a44e9038057dc8d0a39aceb12b26f27fd6d375148e6b81a
Content-Disposition: form-data; name="Filename"

test.jpg
*/
type UploadBodyEle struct {
	boundary string
	key      string
	value    string
}

/*
Use these info to construct the whole upload body string
*/
type UploadBodyInfo struct {
	eleMap      map[string]string
	boundary    string
	fileContent string
}

func initAll() {
	gCurCookies = nil
	gCurCookieJar, _ = cookiejar.New(nil)
	logg := base.NewLogger("log", "log.")
	logger = logg.Log()
}
func ReadUploadFile(filename string) string {
	buf := new(bytes.Buffer)
	w := multipart.NewWriter(buf)

	fw, err := w.CreateFormFile("file", filename)
	if err != nil {
		fmt.Println("c")
	}

	fd, err := os.Open(filename)
	defer fd.Close()
	if err != nil {
		fmt.Println("d")
	}

	_, err = io.Copy(fw, fd)
	if err != nil {
		fmt.Println("e")
	}
	w.Close()

	return buf.String()
}

func ConstructUploadBodyEleStr(ele *UploadBodyEle) string {
	return fmt.Sprintf("--%s\nContent-Disposition: form-data; name=\"%s\"\n\n%s\n", ele.boundary, ele.key, ele.value)
}
func ConstructUploadBodyStr(info *UploadBodyInfo) string {
	var str string
	for _key, _value := range info.eleMap {
		uploadbodyele := &UploadBodyEle{
			boundary: info.boundary,
			key:      _key,
			value:    _value,
		}
		str += ConstructUploadBodyEleStr(uploadbodyele)
	}
	str += fmt.Sprintf("%s\n", info.fileContent)
	return str
}

func ConstructUploadReq(strUrl string, postDict map[string]string, filename string) *http.Request{
	var httpReq *http.Request
	/*------------------------Content----------------------------*/
	file_content := ReadUploadFile(filename)

	info := &UploadBodyInfo{
		eleMap:      postDict,
		boundary:    file_content[2:strings.Index(file_content, "\n")],
		fileContent: file_content,
	}

	postDataStr := ConstructUploadBodyStr(info)

	postBytesReader := bytes.NewReader([]byte(postDataStr))

	httpReq, _ = http.NewRequest("POST", strUrl, postBytesReader)

	/*------------------------Head----------------------------*/
	httpReq.Header.Add("Content-Type", fmt.Sprintf("multipart/form-data; boundary=%s", info.boundary))

	return httpReq
}

func getUrlRespHtml(httpClient *http.Client, strUrl string, postDict map[string]string, filename string) string {
	var httpReq *http.Request
	if nil == postDict {
        logger.Println("---------------is GET------------------")
		httpReq, _ = http.NewRequest("GET", strUrl, nil)
		httpReq.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01")
	} else {
		if filename == "" {
            logger.Println("---------------is POST------------------")
			postValues := url.Values{}
			for postKey, PostValue := range postDict {
				postValues.Set(postKey, PostValue)
			}
			postDataStr := postValues.Encode()
			postBytesReader := bytes.NewReader([]byte(postDataStr))
			httpReq, _ = http.NewRequest("POST", strUrl, postBytesReader)

			httpReq.Header.Add("Content-Type", "application/x-www-form-urlencoded")
		} else {
            logger.Println("---------------is POST Upload------------------")
			httpReq = ConstructUploadReq(strUrl, postDict, filename)
		}
	}

	httpResp, err := httpClient.Do(httpReq)
	if err != nil {
		logger.Println("http get strUrl=%s response error=%s", strUrl, err.Error())
	}

	//logger.Println("httpResp.Status : %s", httpResp.Status)

	defer httpResp.Body.Close()

	body, errReadAll := ioutil.ReadAll(httpResp.Body)
	if errReadAll != nil {
		logger.Println("get response for strUrl=%s got error=%s\n", strUrl, errReadAll.Error())
	}

	gCurCookies = gCurCookieJar.Cookies(httpReq.URL)

	respHtml := string(body)

	return respHtml
}

func PrintCurCookies() {
	var cookieNum int = len(gCurCookies)
	logger.Println("cookieNum=%d", cookieNum)
	for i := 0; i < cookieNum; i++ {
		var curCk *http.Cookie = gCurCookies[i]
		logger.Println("------ Cookie [%d]------", i)
		logger.Println("Name\t\t=%s", curCk.Name)
		logger.Println("Value\t=%s", curCk.Value)
		logger.Println("Path\t\t=%s", curCk.Path)
		logger.Println("Domain\t=%s", curCk.Domain)
		logger.Println("Expires\t=%s", curCk.Expires)
		logger.Println("RawExpires\t=%s", curCk.RawExpires)
		logger.Println("MaxAge\t=%d", curCk.MaxAge)
		logger.Println("Secure\t=%t", curCk.Secure)
		logger.Println("HttpOnly\t=%t", curCk.HttpOnly)
		logger.Println("Raw\t\t=%s", curCk.Raw)
		logger.Println("Unparsed\t=%s", curCk.Unparsed)
	}
}

func main() {

	initAll()

	httpClient := &http.Client{
		Jar: gCurCookieJar,
	}

    //-------------------------------------------页面分割线------------------------------------------
	postDict := map[string]string{}
	postDict["appid"] = "9998"
	postDict["persistentcookie"] = "0"
	postDict["b"] = "7"
	postDict["w"] = "1440"
	postDict["pwdtype"] = "1"
	postDict["v"] = "27"
	postDict["isSLogin"] = "1"
	postDict["ru"] = "https://passport.sohu.com/user/tologin"
	postDict["domain"] = "sohu.com"
	postDict["loginSuccessCallFunction"] = "postLoginSuccessCall"
	postDict["loginFailCallFunction"] = "postLoginFailCall"
	//strUsername := ""
	//strPassword := ""
	//logger.Println("Plese input:")
	//logger.Println("Username:")
	//_, err1 := fmt.Scanln(&strUsername)
	//if nil == err1 {
	//	logger.Println("strUsername=%s", strUsername)
	//}
	//logger.Println("Password:")
	//_, err2 := fmt.Scanln(&strPassword)
	//if nil == err2 {
	//	logger.Println("strPassword=%s", strPassword)
	//}

	//postdict["userid"] = strusername
	//postdict["password"] = strpassword
	postDict["userid"] = "pengnenghui04@sohu.com"
	postDict["password"] = "1775520214"

	logger.Println("postDict=%s", postDict)

	mainLoginUrl := "https://passport.sohu.com/user/login"
	loginRespHtml := getUrlRespHtml(httpClient, mainLoginUrl, postDict,"")
	logger.Println("loginRespHtml=%s", loginRespHtml)
	PrintCurCookies()
    //-------------------------------------------页面分割线------------------------------------------

	toUrl_1 := "http://pp.sohu.com/folders"
	toRespHtml_1 := getUrlRespHtml(httpClient, toUrl_1, nil, "")
	logger.Println("toRespHtml=%s", toRespHtml_1)
	PrintCurCookies()

	m := regexp.MustCompile("\"showId\":\".*\",\"name\":\".*\",\"userId\"")
	list := m.FindStringSubmatch(toRespHtml_1)
	logger.Println(list)
	var toUrl_2 string
	for _, str := range list {
		start := len("\"showId\":\"")
		start_ := len("\",\"name\":\"")
		end := strings.Index(str, "\",\"name\":\"")
		end_ := strings.LastIndex(str, "\",\"userId\"")
		//logger.Println(start,start_,end,end_)
		logger.Println(str[start:end])
		logger.Println(str[start_+end : end_])
		toUrl_2 = fmt.Sprintf("http://pp.sohu.com/upload?folder_id=%s", str[start:end])
	}

    //-------------------------------------------页面分割线------------------------------------------
	logger.Println(toUrl_2)

	postDict_2 := map[string]string{}
	postDict_2["Upload"] = "Submit Query"
	postDict_2["Filename"] = "test.jpg"
	toRespHtml_2 := getUrlRespHtml(httpClient, toUrl_2, postDict_2, "test.jpg")
	logger.Println("toRespHtml=%s", toRespHtml_2)
	PrintCurCookies()
}


get请求很简单,post请求用fidder可以截取到包,通过map[string]string构造

post upload上传复杂一点,不过也是构造fidder截取到的封包



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:realizationmecha

查看原文:golang模拟web上传

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2419 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传