Go SDK files and images
This page covers uploading and downloading files with the Go SDK: Upload a file to get a FileInfo, then send it as an image, voice, video or file message with SendMedia. To download, exchange the file URL in a message for a signed link, or fetch the content directly. For sending messages in general, see Messages; for setting up the client, see Initialization, sign-in and connection.
Upload a file
Upload follows the server's three-step flow: create the upload, PUT the content straight to the presigned URL, then complete it and get a FileInfo. Files can be up to 32 MB:
data, err := os.ReadFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
info, err := c.Upload(ctx, im.UploadInput{
Name: "photo.jpg",
ContentType: "image/jpeg",
Data: data,
Width: 1080, // 可选元数据
Height: 720,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(info.URL, info.Size)UploadInput fields:
| Field | Description |
|---|---|
Name | File name |
ContentType | MIME type; used to infer the kind when Kind is empty |
Data | File content ([]byte, the whole file in memory, ≤32 MB) |
Purpose | What it's for: attachment (message attachment, the default), user_avatar, group_avatar, group_file, chatroom_avatar |
Kind | Kind: image, voice, video, file. When empty it's inferred from ContentType (image/* → image, audio/* → voice, video/* → video, anything else → file) |
Width / Height / DurationMs | Optional metadata (image size, media duration), written into the returned FileInfo on completion and delivered with the message |
Content goes straight to storage
The file content is PUT to a presigned storage URL. It doesn't go through the IM server's API and carries no IM sign-in token. If the PUT returns a non-2xx status, the call fails with *im.APIError (upload_failed), and Message holds the storage response.
- Uploading only gives you a file; it doesn't send a message or change any profile.
- In the returned
FileInfo,URLis the file URL, and images also have a thumbnail URL,ThumbnailURL.Width,HeightandDurationMsare what you passed in and what the server returned on completion.
FileInfo
File information after the upload completes. It can be used directly as the body of an image, voice, video or file message:
| Field | Description |
|---|---|
FileID | File ID |
Name | File name |
Size | Size in bytes |
ContentType | MIME type |
Width / Height | Image width and height in pixels |
DurationMs | Voice or video duration in milliseconds |
URL | File URL (must be exchanged for a download link before loading; see below) |
ThumbnailURL | Thumbnail URL, for image attachments |
SHA256 | Content hash |
Send an image message
SendMedia serializes the FileInfo as the message body and sends it with the msgType you give:
// 1. 上传
data, _ := os.ReadFile("photo.jpg")
info, err := c.Upload(ctx, im.UploadInput{
Name: "photo.jpg",
ContentType: "image/jpeg",
Data: data,
})
if err != nil {
log.Fatal(err)
}
// 2. 作为图片消息发出
m, err := c.SendMedia(ctx, im.ToUser("bob"), "image", info, nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(m.Seq)- Voice messages carry
DurationMs(given throughUploadInput.DurationMswhen uploading), and video can carry width and height, so recipients can lay it out before downloading. - Recipients parse
bodyback intoim.FileInfoas in "Message types" in Messages, usingThumbnailURLfor list thumbnails andURLfor the original. - The
FileInfobecomes the message body as is, so any changes you make toinfobefore sending (such as adding fields) reach the recipient too.
Download
A message attachment's URL is a file URL that can't be requested directly. There are two ways to get the content:
Exchange for signed links. DownloadURLs exchanges up to 100 at a time, with one result per item:
items, err := c.DownloadURLs(ctx, []string{info.URL, info.ThumbnailURL})
if err != nil {
log.Fatal(err)
}
for _, it := range items {
if it.DownloadURL == "" {
fmt.Println(it.URL, it.Code, it.Message) // 失败:file_deleted、forbidden 等
continue
}
fmt.Println(it.DownloadURL, it.ExpiresAt) // 签名直链与到期时间
}Download the content directly. Download exchanges for a link and then GETs it, returning the file bytes:
var body im.FileInfo
_ = json.Unmarshal(m.Body, &body)
data, err := c.Download(ctx, body.URL) // 缩略图传 body.ThumbnailURL
if err != nil {
log.Fatal(err)
}
_ = os.WriteFile(body.Name, data, 0o644)- Links are short-lived (
ExpiresAt). Don't save them or put them in messages; keep the unchanging file URL and exchange it each time you need it. - One bad item doesn't fail the batch: in
DownloadURLsresults, failed items only haveURL,CodeandMessage.Downloadreturns a single item's error as is (file_deleted,forbiddenand so on; check withim.IsCode). Downloadreads the whole content into memory, up to 128 MB. For larger files, get a link withDownloadURLsand stream the download yourself.- Neither exchanging links nor downloading carries the IM sign-in token.
Timeouts and cancellation
- Every method takes a
context.Contextfirst. Cancellingctxstops in-progress REST requests, presigned PUTs and downloads, which suits a cancel button or per-request timeouts. - The overall REST timeout is
Config.HTTPTimeoutfrom when the client was created, 15 seconds by default. For large uploads and downloads, raise it as needed or rely onctx. Uploadsends the whole file in one go; this SDK doesn't do chunked or resumable uploads. Files over 32 MB can't be uploaded withUpload; handle them in your app.- Uploads and downloads don't resume after the process exits. Where delivery must be reliable, retry in your app (uploading again gives a new
FileID).
See also
- Messages:
SendMediaand parsing media messages. - Initialization, sign-in and connection: client options such as
Config.HTTPTimeout.
