From 6294ee3f790762e58042c675f0fe6070a3678733 Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 8 Jul 2024 15:52:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20Material=20=E5=A2=9E=E5=8A=A0=20Add?= =?UTF-8?q?MaterialFromReader=20=E4=B8=8E=20AddVideoFromReader=20=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- officialaccount/material/material.go | 41 +++++++++++++++++++----- util/http.go | 48 ++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 22 deletions(-) diff --git a/officialaccount/material/material.go b/officialaccount/material/material.go index 5b5f1c6bc..8544bb8dc 100644 --- a/officialaccount/material/material.go +++ b/officialaccount/material/material.go @@ -4,6 +4,8 @@ import ( "encoding/json" "errors" "fmt" + "io" + "os" "github.com/silenceper/wechat/v2/officialaccount/context" "github.com/silenceper/wechat/v2/util" @@ -160,8 +162,8 @@ type resAddMaterial struct { URL string `json:"url"` } -// AddMaterial 上传永久性素材(处理视频需要单独上传) -func (material *Material) AddMaterial(mediaType MediaType, filename string) (mediaID string, url string, err error) { +// AddMaterialFromReader 上传永久性素材(处理视频需要单独上传),从 io.Reader 中读取 +func (material *Material) AddMaterialFromReader(mediaType MediaType, filename string, reader io.Reader) (mediaID string, url string, err error) { if mediaType == MediaTypeVideo { err = errors.New("永久视频素材上传使用 AddVideo 方法") return @@ -174,7 +176,7 @@ func (material *Material) AddMaterial(mediaType MediaType, filename string) (med uri := fmt.Sprintf("%s?access_token=%s&type=%s", addMaterialURL, accessToken, mediaType) var response []byte - response, err = util.PostFile("media", filename, uri) + response, err = util.PostFileFromReader("media", filename, reader, uri) if err != nil { return } @@ -192,13 +194,24 @@ func (material *Material) AddMaterial(mediaType MediaType, filename string) (med return } +// AddMaterial 上传永久性素材(处理视频需要单独上传) +func (material *Material) AddMaterial(mediaType MediaType, filename string) (mediaID string, url string, err error) { + f, err := os.Open(filename) + if err != nil { + return + } + defer func() { _ = f.Close() }() + + return material.AddMaterialFromReader(mediaType, filename, f) +} + type reqVideo struct { Title string `json:"title"` Introduction string `json:"introduction"` } -// AddVideo 永久视频素材文件上传 -func (material *Material) AddVideo(filename, title, introduction string) (mediaID string, url string, err error) { +// AddVideoFromReader 永久视频素材文件上传,从 io.Reader 中读取 +func (material *Material) AddVideoFromReader(filename string, reader io.Reader, title, introduction string) (mediaID string, url string, err error) { var accessToken string accessToken, err = material.GetAccessToken() if err != nil { @@ -219,9 +232,10 @@ func (material *Material) AddVideo(filename, title, introduction string) (mediaI fields := []util.MultipartFormField{ { - IsFile: true, - Fieldname: "media", - Filename: filename, + IsFile: true, + Fieldname: "media", + Filename: filename, + FileReader: reader, }, { IsFile: false, @@ -250,6 +264,17 @@ func (material *Material) AddVideo(filename, title, introduction string) (mediaI return } +// AddVideo 永久视频素材文件上传 +func (material *Material) AddVideo(filename, title, introduction string) (mediaID string, url string, err error) { + f, err := os.Open(filename) + if err != nil { + return "", "", err + } + defer func() { _ = f.Close() }() + + return material.AddVideoFromReader(filename, f, title, introduction) +} + type reqDeleteMaterial struct { MediaID string `json:"media_id"` } diff --git a/util/http.go b/util/http.go index 26e4a7be4..24f6dc5d7 100644 --- a/util/http.go +++ b/util/http.go @@ -158,12 +158,26 @@ func PostFile(fieldName, filename, uri string) ([]byte, error) { return PostMultipartForm(fields, uri) } +// PostFileFromReader 上传文件,从 io.Reader 中读取 +func PostFileFromReader(filedName, fileName string, reader io.Reader, uri string) ([]byte, error) { + fields := []MultipartFormField{ + { + IsFile: true, + Fieldname: filedName, + Filename: fileName, + FileReader: reader, + }, + } + return PostMultipartForm(fields, uri) +} + // MultipartFormField 保存文件或其他字段信息 type MultipartFormField struct { - IsFile bool - Fieldname string - Value []byte - Filename string + IsFile bool + Fieldname string + Value []byte + Filename string + FileReader io.Reader } // PostMultipartForm 上传文件或其他多个字段 @@ -182,15 +196,21 @@ func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte return } - fh, e := os.Open(field.Filename) - if e != nil { - err = fmt.Errorf("error opening file , err=%v", e) - return - } - defer fh.Close() - - if _, err = io.Copy(fileWriter, fh); err != nil { - return + if field.FileReader == nil { + fh, e := os.Open(field.Filename) + if e != nil { + err = fmt.Errorf("error opening file , err=%v", e) + return + } + _, err = io.Copy(fileWriter, fh) + _ = fh.Close() + if err != nil { + return + } + } else { + if _, err = io.Copy(fileWriter, field.FileReader); err != nil { + return + } } } else { partWriter, e := bodyWriter.CreateFormField(field.Fieldname) @@ -215,7 +235,7 @@ func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return nil, err + return nil, fmt.Errorf("http code error : uri=%v , statusCode=%v", uri, resp.StatusCode) } respBody, err = io.ReadAll(resp.Body) return From fd2cc099476164cb9f2d18c87489e969ec69cb30 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 9 Jul 2024 20:41:35 +0800 Subject: [PATCH 2/2] =?UTF-8?q?update:=20=E8=B0=83=E6=95=B4=20PostFileFrom?= =?UTF-8?q?Reader=20=E5=8F=82=E6=95=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- officialaccount/material/material.go | 6 +++--- util/http.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/officialaccount/material/material.go b/officialaccount/material/material.go index 8544bb8dc..d8a43b94a 100644 --- a/officialaccount/material/material.go +++ b/officialaccount/material/material.go @@ -176,7 +176,7 @@ func (material *Material) AddMaterialFromReader(mediaType MediaType, filename st uri := fmt.Sprintf("%s?access_token=%s&type=%s", addMaterialURL, accessToken, mediaType) var response []byte - response, err = util.PostFileFromReader("media", filename, reader, uri) + response, err = util.PostFileFromReader("media", filename, uri, reader) if err != nil { return } @@ -211,7 +211,7 @@ type reqVideo struct { } // AddVideoFromReader 永久视频素材文件上传,从 io.Reader 中读取 -func (material *Material) AddVideoFromReader(filename string, reader io.Reader, title, introduction string) (mediaID string, url string, err error) { +func (material *Material) AddVideoFromReader(filename, title, introduction string, reader io.Reader) (mediaID string, url string, err error) { var accessToken string accessToken, err = material.GetAccessToken() if err != nil { @@ -272,7 +272,7 @@ func (material *Material) AddVideo(filename, title, introduction string) (mediaI } defer func() { _ = f.Close() }() - return material.AddVideoFromReader(filename, f, title, introduction) + return material.AddVideoFromReader(filename, title, introduction, f) } type reqDeleteMaterial struct { diff --git a/util/http.go b/util/http.go index 24f6dc5d7..b9b4b004b 100644 --- a/util/http.go +++ b/util/http.go @@ -159,7 +159,7 @@ func PostFile(fieldName, filename, uri string) ([]byte, error) { } // PostFileFromReader 上传文件,从 io.Reader 中读取 -func PostFileFromReader(filedName, fileName string, reader io.Reader, uri string) ([]byte, error) { +func PostFileFromReader(filedName, fileName, uri string, reader io.Reader) ([]byte, error) { fields := []MultipartFormField{ { IsFile: true,