github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/avatars/upload.go (about) 1 // Copyright 2018 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package avatars 5 6 import ( 7 "bytes" 8 "fmt" 9 "io" 10 "mime/multipart" 11 "os" 12 "time" 13 14 "github.com/keybase/client/go/libkb" 15 "github.com/keybase/client/go/protocol/keybase1" 16 ) 17 18 func addFile(mpart *multipart.Writer, param, filename string) error { 19 file, err := os.Open(filename) 20 if err != nil { 21 return err 22 } 23 defer file.Close() 24 25 // do not disclose our filename to the server 26 part, err := mpart.CreateFormFile(param, "image" /* filename */) 27 if err != nil { 28 return err 29 } 30 31 _, err = io.Copy(part, file) 32 return err 33 } 34 35 func UploadImage(mctx libkb.MetaContext, filename string, teamID *keybase1.TeamID, crop *keybase1.ImageCropRect) (err error) { 36 var body bytes.Buffer 37 mpart := multipart.NewWriter(&body) 38 39 if err := addFile(mpart, "avatar", filename); err != nil { 40 mctx.Debug("addFile error: %s", err) 41 return err 42 } 43 44 // Server checks upload size as well. 45 const maxUploadSize = 20 * 1024 * 1024 46 if bodyLen := body.Len(); bodyLen > maxUploadSize { 47 return fmt.Errorf("Image is too big: tried to upload %d bytes, max size is %d bytes.", 48 bodyLen, maxUploadSize) 49 } 50 51 if teamID != nil { 52 err := mpart.WriteField("team_id", string(*teamID)) 53 if err != nil { 54 return err 55 } 56 } 57 58 if crop != nil { 59 mctx.Debug("Adding crop fields: %+v", crop) 60 err := mpart.WriteField("x0", fmt.Sprintf("%d", crop.X0)) 61 if err != nil { 62 return err 63 } 64 err = mpart.WriteField("y0", fmt.Sprintf("%d", crop.Y0)) 65 if err != nil { 66 return err 67 } 68 err = mpart.WriteField("x1", fmt.Sprintf("%d", crop.X1)) 69 if err != nil { 70 return err 71 } 72 err = mpart.WriteField("y1", fmt.Sprintf("%d", crop.Y1)) 73 if err != nil { 74 return err 75 } 76 } 77 78 if err := mpart.Close(); err != nil { 79 return err 80 } 81 82 var endpoint string 83 if teamID != nil { 84 endpoint = "image/upload_team_avatar" 85 } else { 86 endpoint = "image/upload_user_avatar" 87 } 88 89 mctx.Debug("Running POST to %s", endpoint) 90 91 arg := libkb.APIArg{ 92 Endpoint: endpoint, 93 SessionType: libkb.APISessionTypeREQUIRED, 94 InitialTimeout: 5 * time.Minute, 95 RetryCount: 1, 96 } 97 98 _, err = mctx.G().API.PostRaw(mctx, arg, mpart.FormDataContentType(), &body) 99 if err != nil { 100 mctx.Debug("post error: %s", err) 101 return err 102 } 103 104 return nil 105 }