1. 修复formdata类型数据请求失败的问题
2. 新增发送文件的内置方法
This commit is contained in:
parent
d371cc09b3
commit
5c2d74c51d
104
README.MD
104
README.MD
@ -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")
|
||||||
|
|
||||||
#### 2.7.1 设置超时时间
|
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.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)_
|
14
body.go
14
body.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
|
||||||
|
}
|
||||||
|
36
parser.go
36
parser.go
@ -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…
Reference in New Issue
Block a user