package main import ( "encoding/base64" "encoding/json" "fmt" "io/ioutil" "os" ) type crmdFileInfo struct { Name string `json:"name,omitempty"` Type string `json:"type,omitempty"` Role string `json:"role,omitempty"` Size int64 `json:"size,omitempty"` } type crmdAttachmentID struct { ID string `json:"attachmentId"` } type crmdAttachment struct { ID string `json:"id"` //"id": "591e55398345683ee", Name string `json:"name"` //"name": "static_qr_code_without_logo.png", Deleted bool `json:"deleted"` //"deleted": false, Type string `json:"type"` //"type": "image/png", Size int `json:"size"` //"size": 509, SourceID string `json:"sourceId"` //"sourceId": null, CreateAT string `json:"createAt"` //"createdAt": "2017-05-19 02:15:21", Role string `json:"role"` //"role": "Attachment", Storage string `json:"storage"` //"storage": null, StorageFielPath string `json:"storageFilePath"` //"storageFilePath": null, Global bool `json:"global"` // "global": false, ParentID string `json:"parentId"` // "parentId": null, ParentType string `json:"parentType"` // "parentType": null, RelatedID string `json:"relatedId"` // "relatedId": null, RelatedType string `json:"relatedType"` // "relatedType": null, CreatedByID string `json:"createdById"` // "createdById": "1", CreatedbyName string `json:"createdByName"` // "createdByName": "Admin" } func crmUploadFile(path string) (fileID string, fileInfo crmdFileInfo, err error) { fileInfo, err = getFileInfo4CRM(path) headers, err := crmPrepareAttachmentHTTPHeader(fileInfo) data, err := crmFileDataString(path, fileInfo) url := crmUploadAttachmentURL() resp, err := postRAW([]byte(data), url, headers) fileID, err = crmFileIDFromJSON(resp) // log.Println(fileID) // log.Println(err) return } //crmFileIDFromHTTP read attachment id from http response // as http response cannot be 'rewind', this function is // specifically used for one purpose only. // i.e. upload attachment to EspoCRM func crmFileIDFromJSON(jsonStr string) (fileID string, err error) { attach := crmdAttachmentID{} err = json.Unmarshal([]byte(jsonStr), &attach) return attach.ID, err } //crmPrepareAttachmentHTTPHeader when uploading a file, we need its mime, auth header, etc. func crmPrepareAttachmentHTTPHeader(fileInfo crmdFileInfo) (headers map[string]string, err error) { headers = map[string]string{} headers["Authorization"] = crmAuthHeader() headers["Accept"] = "application/json" headers["Content-Type"] = fileInfo.Type return headers, err } func crmUploadAttachmentURL() string { return CRMConfig.apiUploadAttachmentURL() } func crmAuthHeader() string { //return "Basic cGF0cmljazpiNjFmYWRlMTM5OWYwY2ZjNmZjZjcxNTU0OTljNTNkOQ==" s := CRMConfig.UserName + ":" + CRMConfig.UserPass r := base64.StdEncoding.EncodeToString([]byte(s)) return "Basic " + r } //crmFileDataString, encode a base64 string of the given file //so that the receiver EspoCRM can correctly understand and decode it. //"data:image/png;base64,iVB....=" // //TODO: for big files, this might ave issue cause out of memory func crmFileDataString(path string, fileInfo crmdFileInfo) (encoded string, err error) { content, err := ioutil.ReadFile(path) if err != nil { return "", err } b64content := base64.StdEncoding.EncodeToString(content) encoded = fmt.Sprintf("data:%s;base64,%s", fileInfo.Type, b64content) //encode it return encoded, nil } func crmUploadAttachmentMeta(fileID string, fileInfo crmdFileInfo) (resp string, err error) { headers := map[string]string{} headers["Authorization"] = crmAuthHeader() headers["Accept"] = "application/json, text/javascript, */*; q=0.01" headers["Content-Type"] = "application/json" fileInfo.Role = "Attachment" jb, _ := json.Marshal(fileInfo) //log.Println(string(jb)) URL := crmAttachmentMetaURL(fileID) resp, err = putRAW(jb, URL, headers) return } func crmAttachmentMetaURL(fileID string) string { return CRMConfig.apiEntityURL("Attachment", fileID) } func crmCreateAttachment(path string) (result crmdAttachment, err error) { fileID, fileInfo, err := crmUploadFile(path) aInfo, err := crmUploadAttachmentMeta(fileID, fileInfo) if err != nil { return } json.Unmarshal([]byte(aInfo), &result) return } func crmDownloadAttachmentAs(fileID, saveAs string) (err error) { f, err := crmDownloadAttachment(fileID) if err != nil { return } err = os.Rename(f, saveAs) return } func crmDownloadAttachment(fileID string) (filename string, err error) { u := crmURL4DownloadAttachmet(fileID) headers := map[string]string{} headers["Authorization"] = crmAuthHeader() f, _, err := saveURLwithHTTPHeader(u, headers) //log.Println(f) return f, err } func crmURL4DownloadAttachmet(fileID string) string { return CRMConfig.BaseURL + "?entryPoint=download&id=" + fileID }