1. 修复formdata类型数据请求失败的问题

2. 新增发送文件的内置方法
master
徐俊杰 1 year ago
parent d371cc09b3
commit 5c2d74c51d

@ -1,4 +1,4 @@
# simpleRequest _# simpleRequest
## 1. 说明 ## 1. 说明
[simpleRequest](www.github.com/dorlolo/simpleRequest) 是一款面向对象开发的http请求库。他是基于Go原生http库。开发这个模块的主要目的是为了更快的对接http协议的IOT设备。 [simpleRequest](www.github.com/dorlolo/simpleRequest) 是一款面向对象开发的http请求库。他是基于Go原生http库。开发这个模块的主要目的是为了更快的对接http协议的IOT设备。
它具备以下特点: 它具备以下特点:
@ -179,9 +179,95 @@ modeldata:=demo{
r.Body().SetModel(&modeldata) r.Body().SetModel(&modeldata)
``` ```
### 2.7 其它请求参数 ### 2.7 文件上传与转发
### 2.7.1 文件上传
```go
var req = sRequest.NewRequest()
req.Headers().ConentType_formData()
req.Body().
SetFromDataFile("file", "C:\\Users\\lenovo\\Pictures\\Saved Pictures\\demo.jpg").
Set("fromFormat", "jpg").
Set("toFormat", "png")
req.TimeOut(15 * time.Second)
resp, err := req.POST("http://xxx/xxx")
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(string(resp))
```
### 2.7.2 文件转发
下面示例中使用gin作为服务端配合simpleRequest进行文件转发
1. 通过multipart.FileHeader对象进行转发
```go
func FileForwardUseMultipartFile(c *gin.Context){
file,err:=c.FormFile("file")
var req = sRequest.NewRequest()
req.Headers().ConentType_formData()
req.Body().
SetFromDataMultipartFile("file", file).
Set("fromFormat", "jpg").
Set("toFormat", "png")
req.TimeOut(15 * time.Second)
resp, err := req.POST("http://xxx/xxx")
if err != nil {
fmt.Println(err.Error())
return
}
// parse response and so on
// ...
// ...
```
2. 在一些小众场景下可能已经在外部构建好了body此时也可将body转为bytes传入simpleRequest进行请求
```go
func FileForwardUseBytesBody(c *gin.Context){
file,err:=c.FormFile("file")
// body data prepare
vars (
body = &bytes.Buffer{}
writer = multipart.NewWriter(body)
)
// add file object
filePart, _ := i.writer.CreateFormFile("file", file.Filename)
src, err := file.Open()
if err != nil {
fmt.Println( err.Error())
return
}
defer src.Close()
_, err = io.Copy(filePart, src)
if err != nil {
fmt.Println(err.Error())
return
}
// add other form data
writer.WriteField("fromFormat", "jpg")
writer.WriteField("toFormat","png")
// post request
_ = writer.close()
var r = simpleRequest.NewRequest()
req.Headers().SetConentType(writer.FormDataContentType())
req.Body().SetBytes(body.Bytes())
req.TimeOut(15 * time.Second)
resp, err := req.POST("http://xxx/xxx")
if err != nil {
fmt.Println(err.Error())
return
}
// parse response and so on
// ...
// ...
}
```
### 2.8 其它请求参数
#### 2.7.1 设置超时时间 #### 2.8.1 设置超时时间
```go ```go
r.TimeOut(time.Second * 30) r.TimeOut(time.Second * 30)
``` ```
@ -191,8 +277,8 @@ r.TimeOut(time.Second * 30)
r.SkipCertVerify() r.SkipCertVerify()
``` ```
### 2.8 发送请求 ### 2.9 发送请求
#### 2.8.1 post请求 #### 2.9.1 post请求
```go ```go
res, err :=r.POST("https://127.0.0.1:80/excample") res, err :=r.POST("https://127.0.0.1:80/excample")
if err != nil { if err != nil {
@ -213,17 +299,17 @@ if err != nil {
- TRACE - TRACE
### 2.9 获取上下文 ### 2.10 获取上下文
请注意,需要完成请求后才能获得上下文数据! 请注意,需要完成请求后才能获得上下文数据!
#### 2.9.1 获取请求的上下文对象 #### 2.10.1 获取请求的上下文对象
```go ```go
requestContext:=r.Request requestContext:=r.Request
``` ```
#### 2.9.2 获取返回的上下文对象 #### 2.10.2 获取返回的上下文对象
```go ```go
responseContext:=r.Response responseContext:=r.Response
``` ```
## 3. 使用示例 ## 3. 使用示例
[simpleRequest_test.go](excample/simpleRequest_test.go) [simpleRequest_test.go](excample/simpleRequest_test.go)_

@ -7,6 +7,8 @@
package simpleRequest package simpleRequest
import "mime/multipart"
// EntryMark 请求体条目标记用于标记输入的body内容格式 // EntryMark 请求体条目标记用于标记输入的body内容格式
type EntryMark string type EntryMark string
@ -19,6 +21,8 @@ const (
BytesEntryType EntryMark = "__BYTES_ENTRY__" BytesEntryType EntryMark = "__BYTES_ENTRY__"
ModelEntryType EntryMark = "__MODEL_ENTRY__" ModelEntryType EntryMark = "__MODEL_ENTRY__"
MapEntryType EntryMark = "__MAP_ENTRY__" MapEntryType EntryMark = "__MAP_ENTRY__"
MultipartEntryType EntryMark = "__MULTIPART_ENTRY__"
FormFilePathKey EntryMark = "__FORM_FILE_PATH_KEY__"
) )
type BodyConf struct { type BodyConf struct {
@ -53,3 +57,13 @@ func (s *BodyConf) SetModel(model any) *BodyConf {
s.simpleReq.BodyEntries[ModelEntryType.string()] = model s.simpleReq.BodyEntries[ModelEntryType.string()] = model
return s return s
} }
func (s *BodyConf) SetFromDataFile(key, filePath string) *BodyConf {
s.simpleReq.BodyEntryMark = MultipartEntryType
s.simpleReq.BodyEntries[FormFilePathKey.string()+key] = filePath
return s
}
func (s *BodyConf) SetFromDataMultipartFile(key string, multFile *multipart.FileHeader) *BodyConf {
s.simpleReq.BodyEntryMark = MultipartEntryType
s.simpleReq.BodyEntries[key] = multFile
return s
}

@ -1,4 +1,4 @@
// Package simpleRequest ----------------------------- // Package sRequest -----------------------------
// file : parser.go // file : parser.go
// author : JJXu // author : JJXu
// contact : wavingBear@163.com // contact : wavingBear@163.com
@ -11,6 +11,8 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"mime/multipart" "mime/multipart"
"os"
"path/filepath"
"strings" "strings"
) )
@ -76,21 +78,29 @@ func (f *FormDataParser) Unmarshal(bodyType EntryMark, BodyEntry map[string]any)
} }
body, f.ContentType = multipartCommonParse(mapper) body, f.ContentType = multipartCommonParse(mapper)
case StringEntryType: case StringEntryType:
f.ContentType = formDataType
return strings.NewReader(BodyEntry[StringEntryType.string()].(string)) return strings.NewReader(BodyEntry[StringEntryType.string()].(string))
case BytesEntryType: case BytesEntryType:
f.ContentType = formDataType
return bytes.NewReader(BodyEntry[BytesEntryType.string()].([]byte)) return bytes.NewReader(BodyEntry[BytesEntryType.string()].([]byte))
default: default:
body, f.ContentType = multipartCommonParse(BodyEntry) body, f.ContentType = multipartCommonParse(BodyEntry)
} }
f.ContentType = formDataType return
return nil
} }
func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentType string) { func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentType string) {
body := &bytes.Buffer{} body := &bytes.Buffer{}
writer := multipart.NewWriter(body) writer := multipart.NewWriter(body)
for k, sv := range BodyEntry { for k, sv := range BodyEntry {
if strings.Contains(k, FormFilePathKey.string()) {
key := k[len(FormFilePathKey):]
path := sv.(string)
filename := filepath.Base(path)
filePart, _ := writer.CreateFormFile(key, filename)
content, err := os.ReadFile(path)
if err != nil {
panic(err)
}
_, _ = filePart.Write(content)
} else {
switch sv.(type) { switch sv.(type) {
case string: case string:
strSv, _ := sv.(string) strSv, _ := sv.(string)
@ -100,7 +110,23 @@ func multipartCommonParse(BodyEntry map[string]any) (reader io.Reader, contentTy
for _, v := range sss { for _, v := range sss {
_ = writer.WriteField(k, v) _ = writer.WriteField(k, v)
} }
case *multipart.FileHeader:
file, _ := sv.(*multipart.FileHeader)
filePart, _ := writer.CreateFormFile(k, file.Filename)
src, err := file.Open()
if err != nil {
panic(err)
return
}
defer src.Close()
_, err = io.Copy(filePart, src)
if err != nil {
panic(err)
return
}
}
} }
} }
err := writer.Close() err := writer.Close()
if err != nil { if err != nil {

Loading…
Cancel
Save