github.com/chanxuehong/wechat@v0.0.0-20230222024006-36f0325263cd/mp/material/upload.go (about) 1 package material 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 "os" 8 "path/filepath" 9 10 "github.com/chanxuehong/wechat/mp/core" 11 ) 12 13 const ( 14 MaterialTypeImage = "image" 15 MaterialTypeVoice = "voice" 16 MaterialTypeVideo = "video" 17 MaterialTypeThumb = "thumb" 18 MaterialTypeNews = "news" 19 ) 20 21 // image =============================================================================================================== 22 23 // UploadImage 上传多媒体图片 24 func UploadImage(clt *core.Client, _filepath string) (mediaId, url string, err error) { 25 file, err := os.Open(_filepath) 26 if err != nil { 27 return 28 } 29 defer file.Close() 30 31 return UploadImageFromReader(clt, filepath.Base(_filepath), file) 32 } 33 34 // UploadImageFromReader 上传多媒体图片 35 // 36 // NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值. 37 func UploadImageFromReader(clt *core.Client, filename string, reader io.Reader) (mediaId, url string, err error) { 38 const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=image&access_token=" 39 40 var fields = []core.MultipartFormField{ 41 { 42 IsFile: true, 43 Name: "media", 44 FileName: filename, 45 Value: reader, 46 }, 47 } 48 var result struct { 49 core.Error 50 MediaId string `json:"media_id"` 51 URL string `json:"url"` 52 } 53 if err = clt.PostMultipartForm(incompleteURL, fields, &result); err != nil { 54 return 55 } 56 if result.ErrCode != core.ErrCodeOK { 57 err = &result.Error 58 return 59 } 60 mediaId = result.MediaId 61 url = result.URL 62 return 63 } 64 65 // thumb =============================================================================================================== 66 67 // UploadThumb 上传多媒体缩略图 68 func UploadThumb(clt *core.Client, _filepath string) (mediaId, url string, err error) { 69 file, err := os.Open(_filepath) 70 if err != nil { 71 return 72 } 73 defer file.Close() 74 75 return UploadThumbFromReader(clt, filepath.Base(_filepath), file) 76 } 77 78 // UploadThumbFromReader 上传多媒体缩略图 79 // 80 // NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值. 81 func UploadThumbFromReader(clt *core.Client, filename string, reader io.Reader) (mediaId, url string, err error) { 82 const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=thumb&access_token=" 83 84 var fields = []core.MultipartFormField{ 85 { 86 IsFile: true, 87 Name: "media", 88 FileName: filename, 89 Value: reader, 90 }, 91 } 92 var result struct { 93 core.Error 94 MediaId string `json:"media_id"` 95 URL string `json:"url"` 96 } 97 if err = clt.PostMultipartForm(incompleteURL, fields, &result); err != nil { 98 return 99 } 100 if result.ErrCode != core.ErrCodeOK { 101 err = &result.Error 102 return 103 } 104 mediaId = result.MediaId 105 url = result.URL 106 return 107 } 108 109 // voice =============================================================================================================== 110 111 // UploadVoice 上传多媒体语音 112 func UploadVoice(clt *core.Client, _filepath string) (mediaId string, err error) { 113 file, err := os.Open(_filepath) 114 if err != nil { 115 return 116 } 117 defer file.Close() 118 119 return UploadVoiceFromReader(clt, filepath.Base(_filepath), file) 120 } 121 122 // UploadVoiceFromReader 上传多媒体语音 123 // 124 // NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值. 125 func UploadVoiceFromReader(clt *core.Client, filename string, reader io.Reader) (mediaId string, err error) { 126 const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=voice&access_token=" 127 128 var fields = []core.MultipartFormField{ 129 { 130 IsFile: true, 131 Name: "media", 132 FileName: filename, 133 Value: reader, 134 }, 135 } 136 var result struct { 137 core.Error 138 MediaId string `json:"media_id"` 139 } 140 if err = clt.PostMultipartForm(incompleteURL, fields, &result); err != nil { 141 return 142 } 143 if result.ErrCode != core.ErrCodeOK { 144 err = &result.Error 145 return 146 } 147 mediaId = result.MediaId 148 return 149 } 150 151 // video =============================================================================================================== 152 153 // UploadVideo 上传多媒体视频. 154 func UploadVideo(clt *core.Client, _filepath string, title, introduction string) (mediaId string, err error) { 155 file, err := os.Open(_filepath) 156 if err != nil { 157 return 158 } 159 defer file.Close() 160 161 return UploadVideoFromReader(clt, filepath.Base(_filepath), file, title, introduction) 162 } 163 164 // UploadVideoFromReader 上传多媒体缩视频. 165 // 166 // NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值. 167 func UploadVideoFromReader(clt *core.Client, filename string, reader io.Reader, title, introduction string) (mediaId string, err error) { 168 const incompleteURL = "https://api.weixin.qq.com/cgi-bin/material/add_material?type=video&access_token=" 169 170 buffer := bytes.NewBuffer(make([]byte, 0, 256)) 171 encoder := json.NewEncoder(buffer) 172 encoder.SetEscapeHTML(false) 173 174 var description = struct { 175 Title string `json:"title"` 176 Introduction string `json:"introduction"` 177 }{ 178 Title: title, 179 Introduction: introduction, 180 } 181 if err = encoder.Encode(&description); err != nil { 182 return 183 } 184 descriptionBytes := buffer.Bytes() 185 186 var fields = []core.MultipartFormField{ 187 { 188 IsFile: true, 189 Name: "media", 190 FileName: filename, 191 Value: reader, 192 }, 193 { 194 IsFile: false, 195 Name: "description", 196 Value: bytes.NewReader(descriptionBytes), 197 }, 198 } 199 var result struct { 200 core.Error 201 MediaId string `json:"media_id"` 202 } 203 if err = clt.PostMultipartForm(incompleteURL, fields, &result); err != nil { 204 return 205 } 206 if result.ErrCode != core.ErrCodeOK { 207 err = &result.Error 208 return 209 } 210 mediaId = result.MediaId 211 return 212 }