Skip to content

Commit ed149ad

Browse files
committed
add stream_upload_source
1 parent 05ac714 commit ed149ad

File tree

4 files changed

+119
-15
lines changed

4 files changed

+119
-15
lines changed

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 {

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) {

util/http.go

+21-7
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ import (
88
"encoding/pem"
99
"encoding/xml"
1010
"fmt"
11+
"golang.org/x/crypto/pkcs12"
1112
"io"
1213
"log"
1314
"mime/multipart"
1415
"net/http"
1516
"os"
16-
17-
"golang.org/x/crypto/pkcs12"
1817
)
1918

2019
// URIModifier URI修改器
@@ -146,24 +145,38 @@ func PostJSONWithRespContentType(uri string, obj interface{}) ([]byte, string, e
146145
return responseData, contentType, err
147146
}
148147

148+
// PostFileByStream 上传文件
149+
func PostFileByStream(fieldName, fileName, uri string, byteData []byte) ([]byte, error) {
150+
fields := []MultipartFormField{
151+
{
152+
IsFile: false,
153+
Fieldname: fieldName,
154+
Filename: fileName,
155+
Value: byteData,
156+
},
157+
}
158+
return PostMultipartForm(fields, uri)
159+
}
160+
149161
// PostFile 上传文件
150-
func PostFile(fieldName, filename, uri string) ([]byte, error) {
162+
func PostFile(fieldName, filePath, uri string) ([]byte, error) {
151163
fields := []MultipartFormField{
152164
{
153165
IsFile: true,
154166
Fieldname: fieldName,
155-
Filename: filename,
167+
FilePath: filePath,
156168
},
157169
}
158170
return PostMultipartForm(fields, uri)
159171
}
160172

161173
// PostFileFromReader 上传文件,从 io.Reader 中读取
162-
func PostFileFromReader(filedName, fileName, uri string, reader io.Reader) ([]byte, error) {
174+
func PostFileFromReader(filedName, filePath, fileName, uri string, reader io.Reader) ([]byte, error) {
163175
fields := []MultipartFormField{
164176
{
165177
IsFile: true,
166178
Fieldname: filedName,
179+
FilePath: filePath,
167180
Filename: fileName,
168181
FileReader: reader,
169182
},
@@ -176,6 +189,7 @@ type MultipartFormField struct {
176189
IsFile bool
177190
Fieldname string
178191
Value []byte
192+
FilePath string
179193
Filename string
180194
FileReader io.Reader
181195
}
@@ -197,7 +211,7 @@ func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte
197211
}
198212

199213
if field.FileReader == nil {
200-
fh, e := os.Open(field.Filename)
214+
fh, e := os.Open(field.FilePath)
201215
if e != nil {
202216
err = fmt.Errorf("error opening file , err=%v", e)
203217
return
@@ -213,7 +227,7 @@ func PostMultipartForm(fields []MultipartFormField, uri string) (respBody []byte
213227
}
214228
}
215229
} else {
216-
partWriter, e := bodyWriter.CreateFormField(field.Fieldname)
230+
partWriter, e := bodyWriter.CreateFormFile(field.Fieldname, field.Filename)
217231
if e != nil {
218232
err = e
219233
return

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)