github.com/chanxuehong/wechat@v0.0.0-20230222024006-36f0325263cd/mp/media/upload.go (about)

     1  package media
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/chanxuehong/wechat/mp/core"
     9  )
    10  
    11  const (
    12  	MediaTypeImage = "image"
    13  	MediaTypeVoice = "voice"
    14  	MediaTypeVideo = "video"
    15  	MediaTypeThumb = "thumb"
    16  	MediaTypeNews  = "news"
    17  )
    18  
    19  type MediaInfo struct {
    20  	MediaType string `json:"type"`       // 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb,主要用于视频与音乐格式的缩略图)
    21  	MediaId   string `json:"media_id"`   // 媒体文件上传后,获取时的唯一标识
    22  	CreatedAt int64  `json:"created_at"` // 媒体文件上传时间戳
    23  }
    24  
    25  // UploadImage 上传多媒体图片
    26  func UploadImage(clt *core.Client, filepath string) (info *MediaInfo, err error) {
    27  	return upload(clt, MediaTypeImage, filepath)
    28  }
    29  
    30  // UploadImageFromReader 上传多媒体图片
    31  //
    32  //	NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值.
    33  func UploadImageFromReader(clt *core.Client, filename string, reader io.Reader) (info *MediaInfo, err error) {
    34  	return uploadFromReader(clt, MediaTypeImage, filename, reader)
    35  }
    36  
    37  // UploadVoice 上传多媒体语音
    38  func UploadVoice(clt *core.Client, filepath string) (info *MediaInfo, err error) {
    39  	return upload(clt, MediaTypeVoice, filepath)
    40  }
    41  
    42  // UploadVoiceFromReader 上传多媒体语音
    43  //
    44  //	NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值.
    45  func UploadVoiceFromReader(clt *core.Client, filename string, reader io.Reader) (info *MediaInfo, err error) {
    46  	return uploadFromReader(clt, MediaTypeVoice, filename, reader)
    47  }
    48  
    49  // UploadVideo 上传多媒体视频
    50  func UploadVideo(clt *core.Client, filepath string) (info *MediaInfo, err error) {
    51  	return upload(clt, MediaTypeVideo, filepath)
    52  }
    53  
    54  // UploadVideoFromReader 上传多媒体视频
    55  //
    56  //	NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值.
    57  func UploadVideoFromReader(clt *core.Client, filename string, reader io.Reader) (info *MediaInfo, err error) {
    58  	return uploadFromReader(clt, MediaTypeVideo, filename, reader)
    59  }
    60  
    61  // =====================================================================================================================
    62  
    63  func upload(clt *core.Client, mediaType, _filepath string) (info *MediaInfo, err error) {
    64  	file, err := os.Open(_filepath)
    65  	if err != nil {
    66  		return
    67  	}
    68  	defer file.Close()
    69  
    70  	return uploadFromReader(clt, mediaType, filepath.Base(_filepath), file)
    71  }
    72  
    73  func uploadFromReader(clt *core.Client, mediaType, filename string, reader io.Reader) (info *MediaInfo, err error) {
    74  	var incompleteURL = "https://api.weixin.qq.com/cgi-bin/media/upload?type=" + mediaType + "&access_token="
    75  
    76  	var fields = []core.MultipartFormField{
    77  		{
    78  			IsFile:   true,
    79  			Name:     "media",
    80  			FileName: filename,
    81  			Value:    reader,
    82  		},
    83  	}
    84  	var result struct {
    85  		core.Error
    86  		MediaInfo
    87  	}
    88  	if err = clt.PostMultipartForm(incompleteURL, fields, &result); err != nil {
    89  		return
    90  	}
    91  	if result.ErrCode != core.ErrCodeOK {
    92  		err = &result.Error
    93  		return
    94  	}
    95  	info = &result.MediaInfo
    96  	return
    97  }
    98  
    99  // =====================================================================================================================
   100  
   101  // UploadThumb 上传多媒体缩略图
   102  func UploadThumb(clt *core.Client, _filepath string) (info *MediaInfo, err error) {
   103  	file, err := os.Open(_filepath)
   104  	if err != nil {
   105  		return
   106  	}
   107  	defer file.Close()
   108  
   109  	return UploadThumbFromReader(clt, filepath.Base(_filepath), file)
   110  }
   111  
   112  // UploadThumbFromReader 上传多媒体缩略图.
   113  //
   114  //	NOTE: 参数 filename 不是文件路径, 是 multipart/form-data 里面 filename 的值.
   115  func UploadThumbFromReader(clt *core.Client, filename string, reader io.Reader) (info *MediaInfo, err error) {
   116  	const incompleteURL = "https://api.weixin.qq.com/cgi-bin/media/upload?type=thumb&access_token="
   117  
   118  	var fields = []core.MultipartFormField{
   119  		{
   120  			IsFile:   true,
   121  			Name:     "media",
   122  			FileName: filename,
   123  			Value:    reader,
   124  		},
   125  	}
   126  	var result struct {
   127  		core.Error
   128  		MediaType string `json:"type"`
   129  		MediaId   string `json:"thumb_media_id"`
   130  		CreatedAt int64  `json:"created_at"`
   131  	}
   132  	if err = clt.PostMultipartForm(incompleteURL, fields, &result); err != nil {
   133  		return
   134  	}
   135  	if result.ErrCode != core.ErrCodeOK {
   136  		err = &result.Error
   137  		return
   138  	}
   139  	info = &MediaInfo{
   140  		MediaType: result.MediaType,
   141  		MediaId:   result.MediaId,
   142  		CreatedAt: result.CreatedAt,
   143  	}
   144  	return
   145  }