Skip to content

Commit a8e6bce

Browse files
committed
add stream_upload_source
1 parent 05ac714 commit a8e6bce

File tree

4 files changed

+118
-13
lines changed

4 files changed

+118
-13
lines changed

Diff for: officialaccount/material/material.go

+13-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"os"
9+
"path"
910

1011
"github.com/silenceper/wechat/v2/officialaccount/context"
1112
"github.com/silenceper/wechat/v2/util"
@@ -163,7 +164,7 @@ type resAddMaterial struct {
163164
}
164165

165166
// AddMaterialFromReader 上传永久性素材(处理视频需要单独上传),从 io.Reader 中读取
166-
func (material *Material) AddMaterialFromReader(mediaType MediaType, filename string, reader io.Reader) (mediaID string, url string, err error) {
167+
func (material *Material) AddMaterialFromReader(mediaType MediaType, filePath string, reader io.Reader) (mediaID string, url string, err error) {
167168
if mediaType == MediaTypeVideo {
168169
err = errors.New("永久视频素材上传使用 AddVideo 方法")
169170
return
@@ -175,8 +176,10 @@ func (material *Material) AddMaterialFromReader(mediaType MediaType, filename st
175176
}
176177

177178
uri := fmt.Sprintf("%s?access_token=%s&type=%s", addMaterialURL, accessToken, mediaType)
179+
// 获取文件名
180+
filename := path.Base(filePath)
178181
var response []byte
179-
response, err = util.PostFileFromReader("media", filename, uri, reader)
182+
response, err = util.PostFileFromReader("media", filePath, filename, uri, reader)
180183
if err != nil {
181184
return
182185
}
@@ -211,7 +214,7 @@ type reqVideo struct {
211214
}
212215

213216
// AddVideoFromReader 永久视频素材文件上传,从 io.Reader 中读取
214-
func (material *Material) AddVideoFromReader(filename, title, introduction string, reader io.Reader) (mediaID string, url string, err error) {
217+
func (material *Material) AddVideoFromReader(filePath, title, introduction string, reader io.Reader) (mediaID string, url string, err error) {
215218
var accessToken string
216219
accessToken, err = material.GetAccessToken()
217220
if err != nil {
@@ -229,17 +232,19 @@ func (material *Material) AddVideoFromReader(filename, title, introduction strin
229232
if err != nil {
230233
return
231234
}
232-
235+
fileName := path.Base(filePath)
233236
fields := []util.MultipartFormField{
234237
{
235238
IsFile: true,
236239
Fieldname: "media",
237-
Filename: filename,
240+
FilePath: filePath,
241+
Filename: fileName,
238242
FileReader: reader,
239243
},
240244
{
241245
IsFile: false,
242246
Fieldname: "description",
247+
Filename: fileName,
243248
Value: fieldValue,
244249
},
245250
}
@@ -265,14 +270,14 @@ func (material *Material) AddVideoFromReader(filename, title, introduction strin
265270
}
266271

267272
// AddVideo 永久视频素材文件上传
268-
func (material *Material) AddVideo(filename, title, introduction string) (mediaID string, url string, err error) {
269-
f, err := os.Open(filename)
273+
func (material *Material) AddVideo(directory, title, introduction string) (mediaID string, url string, err error) {
274+
f, err := os.Open(directory)
270275
if err != nil {
271276
return "", "", err
272277
}
273278
defer func() { _ = f.Close() }()
274279

275-
return material.AddVideoFromReader(filename, title, introduction, f)
280+
return material.AddVideoFromReader(directory, title, introduction, f)
276281
}
277282

278283
type reqDeleteMaterial struct {

Diff for: officialaccount/material/media.go

+33
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package material
33
import (
44
"encoding/json"
55
"fmt"
6+
"io"
67

78
"github.com/silenceper/wechat/v2/util"
89
)
@@ -62,6 +63,38 @@ func (material *Material) MediaUpload(mediaType MediaType, filename string) (med
6263
return
6364
}
6465

66+
// MediaUploadFromReader 临时素材上传
67+
func (material *Material) MediaUploadFromReader(mediaType MediaType, filename string, reader io.Reader) (media Media, err error) {
68+
var accessToken string
69+
accessToken, err = material.GetAccessToken()
70+
if err != nil {
71+
return
72+
}
73+
74+
uri := fmt.Sprintf("%s?access_token=%s&type=%s", mediaUploadURL, accessToken, mediaType)
75+
76+
var byteData []byte
77+
byteData, err = io.ReadAll(reader)
78+
if err != nil {
79+
return
80+
}
81+
82+
var response []byte
83+
response, err = util.PostFileByStream("media", filename, uri, byteData)
84+
if err != nil {
85+
return
86+
}
87+
err = json.Unmarshal(response, &media)
88+
if err != nil {
89+
return
90+
}
91+
if media.ErrCode != 0 {
92+
err = fmt.Errorf("MediaUpload error : errcode=%v , errmsg=%v", media.ErrCode, media.ErrMsg)
93+
return
94+
}
95+
return
96+
}
97+
6598
// GetMediaURL 返回临时素材的下载地址供用户自己处理
6699
// NOTICE: URL 不可公开,因为含access_token 需要立即另存文件
67100
func (material *Material) GetMediaURL(mediaID string) (mediaURL string, err error) {

Diff for: util/http.go

+20-5
Original file line numberDiff line numberDiff line change
@@ -146,24 +146,38 @@ func PostJSONWithRespContentType(uri string, obj interface{}) ([]byte, string, e
146146
return responseData, contentType, err
147147
}
148148

149+
// PostFileByStream 上传文件
150+
func PostFileByStream(fieldName, fileName, uri string, byteData []byte) ([]byte, error) {
151+
fields := []MultipartFormField{
152+
{
153+
IsFile: false,
154+
Fieldname: fieldName,
155+
Filename: fileName,
156+
Value: byteData,
157+
},
158+
}
159+
return PostMultipartForm(fields, uri)
160+
}
161+
149162
// PostFile 上传文件
150-
func PostFile(fieldName, filename, uri string) ([]byte, error) {
163+
func PostFile(fieldName, filePath, uri string) ([]byte, error) {
151164
fields := []MultipartFormField{
152165
{
153166
IsFile: true,
154167
Fieldname: fieldName,
155-
Filename: filename,
168+
FilePath: filePath,
156169
},
157170
}
158171
return PostMultipartForm(fields, uri)
159172
}
160173

161174
// PostFileFromReader 上传文件,从 io.Reader 中读取
162-
func PostFileFromReader(filedName, fileName, uri string, reader io.Reader) ([]byte, error) {
175+
func PostFileFromReader(filedName, filePath, fileName, uri string, reader io.Reader) ([]byte, error) {
163176
fields := []MultipartFormField{
164177
{
165178
IsFile: true,
166179
Fieldname: filedName,
180+
FilePath: filePath,
167181
Filename: fileName,
168182
FileReader: reader,
169183
},
@@ -176,6 +190,7 @@ type MultipartFormField struct {
176190
IsFile bool
177191
Fieldname string
178192
Value []byte
193+
FilePath string
179194
Filename string
180195
FileReader io.Reader
181196
}
@@ -197,7 +212,7 @@ func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte
197212
}
198213

199214
if field.FileReader == nil {
200-
fh, e := os.Open(field.Filename)
215+
fh, e := os.Open(field.FilePath)
201216
if e != nil {
202217
err = fmt.Errorf("error opening file , err=%v", e)
203218
return
@@ -213,7 +228,7 @@ func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte
213228
}
214229
}
215230
} else {
216-
partWriter, e := bodyWriter.CreateFormField(field.Fieldname)
231+
partWriter, e := bodyWriter.CreateFormFile(field.Fieldname, field.Filename)
217232
if e != nil {
218233
err = e
219234
return

Diff for: work/material/media.go

+52
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package material
22

33
import (
44
"fmt"
5+
"io"
56

67
"github.com/silenceper/wechat/v2/util"
78
)
@@ -96,3 +97,54 @@ func (r *Client) UploadAttachment(filename string, mediaType string, attachmentT
9697
err = util.DecodeWithError(response, result, "UploadAttachment")
9798
return result, err
9899
}
100+
101+
// UploadTempFileFromReader 上传临时素材
102+
// @see https://developer.work.weixin.qq.com/document/path/90253
103+
// @mediaType 媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file)
104+
func (r *Client) UploadTempFileFromReader(filename, mediaType string, reader io.Reader) (*UploadTempFileResponse, error) {
105+
var (
106+
accessToken string
107+
err error
108+
)
109+
if accessToken, err = r.GetAccessToken(); err != nil {
110+
return nil, err
111+
}
112+
var byteData []byte
113+
byteData, err = io.ReadAll(reader)
114+
if err != nil {
115+
return nil, err
116+
}
117+
var response []byte
118+
if response, err = util.PostFileByStream("media", filename, fmt.Sprintf(uploadTempFile, accessToken, mediaType), byteData); err != nil {
119+
return nil, err
120+
}
121+
result := &UploadTempFileResponse{}
122+
err = util.DecodeWithError(response, result, "UploadTempFile")
123+
return result, err
124+
}
125+
126+
// UploadAttachmentFromReader 上传附件资源
127+
// @see https://developer.work.weixin.qq.com/document/path/95098
128+
// @mediaType 媒体文件类型,分别有图片(image)、视频(video)、普通文件(file)
129+
// @attachment_type 附件类型,不同的附件类型用于不同的场景。1:朋友圈;2:商品图册
130+
func (r *Client) UploadAttachmentFromReader(filename, mediaType string, reader io.Reader, attachmentType int) (*UploadAttachmentResponse, error) {
131+
var (
132+
accessToken string
133+
err error
134+
)
135+
if accessToken, err = r.GetAccessToken(); err != nil {
136+
return nil, err
137+
}
138+
var byteData []byte
139+
byteData, err = io.ReadAll(reader)
140+
if err != nil {
141+
return nil, err
142+
}
143+
var response []byte
144+
if response, err = util.PostFileByStream("media", filename, fmt.Sprintf(uploadAttachment, accessToken, mediaType, attachmentType), byteData); err != nil {
145+
return nil, err
146+
}
147+
result := &UploadAttachmentResponse{}
148+
err = util.DecodeWithError(response, result, "UploadAttachment")
149+
return result, err
150+
}

0 commit comments

Comments
 (0)