Getting unexpected directory name in json output in Golang server - go

I am new in Golang and I am trying to store image in the files on server and save its directory in MySQL Database. The code is running fine the DB is also storing the directory of the stored image correctly but the output json is showing the directory not correctly and I am not able to solve this. If also possible I want to give proper name to the saved file while creating and storing the image in the directory.I know should use jpeg or png but don't know how to set directory for these. The Directory has a parent folder profile-pic and child folder created from the mobile number I get form the POST Request where the image is stored. The Code is given below main.go
func main() {
host, _ := os.Hostname()
addrs, _ := net.LookupIP(host)
for _, addr := range addrs {
if ipv4 := addr.To4(); ipv4 != nil {
fmt.Println("IPv4: ", ipv4)
}
}
r := httprouter.New()
uc := controller.NewUserController(getSession())
r.GET("/", uc.Starter)
r.POST("/create", uc.MobileCreate)
http.ListenAndServe(":8080", r)
}
func getSession() *sql.DB {
s, err := sql.Open("mysql", "root:password#tcp(127.0.0.1:3306)/test")
if err != nil {
panic(err)
}
return s
}
controller.go
type UserController struct {
session *sql.DB
}
func NewUserController(s *sql.DB) *UserController {
return &UserController{s}
}
func (uc UserController) Starter(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
dump, err := httputil.DumpRequest(r, true)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `Your at homepage and Connection to db was success and check the terminal for dump diagnosis!`)
fmt.Println("Request Dump:\n", string(dump))
}
func (uc UserController) MobileCreate(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
r.ParseMultipartForm(10 << 20)
UserName := r.FormValue("name")
EmailId := r.FormValue("email")
PassWord := r.FormValue("password")
MobileNumber := r.FormValue("mobile")
i, _ := strconv.ParseInt(MobileNumber, 0, 64)
AddRess := r.FormValue("address")
ProfilePic, _, err := r.FormFile("profilePic")
DirectoryName := "profile-pics" + "\\" + MobileNumber
_ = DirectoryName + "\\" + "dp.png"
if err != nil {
fmt.Println("Error Retrieving the File")
fmt.Println(err)
return
}
defer ProfilePic.Close()
_, err = os.Stat("test")
if os.IsNotExist(err) {
errDir := os.MkdirAll("profile-pics"+"\\"+MobileNumber, 0755)
if errDir != nil {
log.Fatal(err)
}
}
tempFile, err := ioutil.TempFile("profile-pics"+"\\"+MobileNumber, "*.png")
if err != nil {
fmt.Println(err)
}
defer tempFile.Close()
fileBytes, err := ioutil.ReadAll(ProfilePic)
if err != nil {
fmt.Println(err)
}
// write this byte array to our temporary file
tempFile.Write(fileBytes)
u := models.User{
Name: UserName,
Email: EmailId,
Password: PassWord,
Mobile: i,
Address: AddRess,
ProfilePic: tempFile.Name(),
}
query, err := uc.session.Prepare("Insert loggedin SET name=?, email=?,pwd=?,number=?,address=?,profilepic=?")
if err != nil {
panic(err)
}
_, err = query.Exec(u.Name, u.Email, u.Password, u.Mobile, u.Address, u.ProfilePic)
if err != nil {
panic(err)
}
defer query.Close()
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated) // 201
err = json.NewEncoder(w).Encode(u)
if err != nil {
fmt.Println(err)
}
}
model/user.go
type User struct {
Name string `json:"name" `
Email string `json:"email" `
Password string `json:"password" `
Mobile int64 `json:"mobile" `
Address string `json:"address" `
ProfilePic string `json: image`
}
The entry in database is correct
The json Output
"profile-pics\\9041111113\\103561439.png"
I tried naming the img to dp but the img was then saved in unsupported format
I want to remove double \\because i have to load this image in android app with picasso lib and it doesn't convert \\ to single \
Picasso.get()
.load(json output as string)
.into(imageView)
I want to save the image in png only.

Related

How to upload image or file as backend

I don't know how to upload image or file in Go. Here I share my code
this is my repository, what i must change or add more code?
func (db *reportConnection) CreateReport(report entity.Report) entity.Report {
db.connection.Save(&report)
db.connection.Preload("User").Find(&report)
return report
}
this is my service, what i must change or add more code?
func (service *reportService) Create(r dto.ReportCreateDTO) entity.Report {
report := entity.Report{}
err := smapping.FillStruct(&report, smapping.MapFields(&r))
if err != nil {
log.Fatalf("failed map %v: ", err)
}
res := service.reportRepo.CreateReport(report)
return res
}
this is my controller, what i must change or add more code?
func (c *reportController) Create(ctx *gin.Context) {
var createReport dto.ReportCreateDTO
err := ctx.ShouldBind(&createReport)
if err != nil {
response := response.BuildErrorResponse("Failed to process!", err.Error(), response.EmptyObj{})
ctx.AbortWithStatusJSON(http.StatusBadRequest, response)
} else {
authHeader := ctx.GetHeader("Authorization")
userID := c.GetUserIDByToken(authHeader)
convertUserID, err := strconv.ParseUint(userID, 10, 64)
if err == nil {
createReport.UserID = convertUserID
}
result := c.reportService.Create(createReport)
response := response.BuildResponse(true, "OK!", result)
ctx.JSON(http.StatusOK, response)
}
}
```
i think i need to set a header, but not sure how

Getting data from Firestore to display a go template file

How can I get the p.template from firestore, which is a string, into template.ParseFiles function? Is it possible to use the field value in the function to select the correct template file?
type Property struct {
Name string `firestore:"name"`
ApprovedOrigins []interface{} `firestore:"approvedOrigins"`
Template string `firestore:"selected"`
}
As you can see above the firestore field name is selected
func serveHandler(w http.ResponseWriter, r *http.Request, params map[string]string) {
ctx := context.Background()
client, err := firestore.NewClient(ctx, projectId)
if err != nil {
// TODO: Handle error.
log.Println("FIREBASE ERROR:", err)
}
// collection group query in firestore
q := client.CollectionGroup("data").Where("approvedOrigins", "array-contains", r.Host).Limit(1)
// iterate through the document query
iter := q.Documents(ctx)
defer iter.Stop()
for {
doc, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
// TODO: Handle error.
log.Println("FIREBASE ERROR:", err)
}
fmt.Println("Database connected...")
var p Property
if err := doc.DataTo(&p); err != nil {
fmt.Println(err)
}
fmt.Println(p.Template) // This is not logging any data/string
t, _ := template.ParseFiles(p.Template + ".html")
fmt.Println(t.Execute(w, p)) //504 error happens here
}
}

How do I send an http post request with image and with some parameters in Go?

I am trying to make an http post request with image and parameters in the form-data, but when I am adding image, my parameters are lost.
testProduct := &Product{
Name: "TestProductName",
ImageExtension: "png",
}
var b bytes.Buffer
multipartWriter := multipart.NewWriter(&b)
multipartWriter.CreateFormFile("image", "../test.png")
multipartWriter.Close()
form = url.Values{}
form.Add("name", testProduct.Name)
form.Add("image_extension", testProduct.ImageExtension)
req, _ := http.NewRequest(http.MethodPost, "api/v1/admin/products/", &b)
req.PostForm = form
req.Header.Add("Authorization", "Bearer "+loginResponse.Token)
req.Header.Set("Content-Type", multipartWriter.FormDataContentType())
recorder := httptest.NewRecorder()
router.ServeHTTP(recorder, req)
But when the request handled the parameters doesn't bind:
https://i.imgur.com/JmT4qLh.png
This is the product struct:
type Product struct {
ID string `form:"id" json:"id"`
Name string `form:"name" json:"name"`
Price int64 `form:"price" json:"price"`
ImageExtension string `form:"image_extension" json:"image_extension"`
}
testProduct := &Product{
Name: "TestProductName",
ImageExtension: "png",
}
pr, pw := io.Pipe()
form := multipart.NewWriter(pw)
go func() {
defer pw.Close()
err := form.WriteField("name", testProduct.Name)
if err != nil {
return
}
err = form.WriteField("image_extension", testProduct.ImageExtension)
file, err := os.Open("a.png") // path to image file
if err != nil {
return
}
w, err := form.CreateFormFile("image", "sampleImageFileName.png")
if err != nil {
return
}
_, err = io.Copy(w, file)
if err != nil {
return
}
form.Close()
}()
r, err := http.NewRequest(http.MethodPost, "api/v1/admin/products/", pr)
if err != nil {
return
}
r.Header.Set("Content-Type", form.FormDataContentType())

Upload a file with POST request golang

I'm new to golang and I'm trying to write a function that uploads a file with a post request to telegram for a bot I'm writing.
I've tried with this code but the error I'm getting from telegram is
Bad Request: there is no photo in the request.
I've searched on the net for how to do that, but none of what I found helped me through the problem.
func SendPostRequest (url string, filename string) []byte {
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer file.Close()
response, err := http.Post(url, "binary/octet-stream", file)
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
content, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
return content
}
The function I'm calling the SendPostRequest from is
func (e Engine) SendPhoto (filename string, chatId int64) APIResponse {
var url = fmt.Sprintf("%ssendPhoto?chat_id=%d", e.baseUrl, chatId)
var content []byte = SendPostRequest(url, filename)
var response APIResponse
json.Unmarshal(content, &response)
return response
}
EDIT:
The link to the Telegram bot api I'm using in the code is https://core.telegram.org/bots/api
And the api method is https://core.telegram.org/bots/api#sendphoto
After some digging I figured it out with this
import (
"bytes"
"io"
"mime/multipart"
"net/http"
"path/filepath"
)
// content is a struct which contains a file's name, its type and its data.
type content struct {
fname string
ftype string
fdata []byte
}
func sendPostRequest(url string, files ...content) ([]byte, error) {
var (
buf = new(bytes.Buffer)
w = multipart.NewWriter(buf)
)
for _, f := range files {
part, err := w.CreateFormFile(f.ftype, filepath.Base(f.fname))
if err != nil {
return []byte{}, err
}
_, err = part.Write(f.fdata)
if err != nil {
return []byte{}, err
}
}
err := w.Close()
if err != nil {
return []byte{}, err
}
req, err := http.NewRequest("POST", url, buf)
if err != nil {
return []byte{}, err
}
req.Header.Add("Content-Type", w.FormDataContentType())
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return []byte{}, err
}
defer res.Body.Close()
cnt, err := io.ReadAll(res.Body)
if err != nil {
return []byte{}, err
}
return cnt, nil
}

Send email with attachments in golang

Here is the code:
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"os"
"os/user"
"path/filepath"
"golang.org/x/net/context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/gmail/v1"
"encoding/base64"
"io/ioutil"
)
// getClient uses a Context and Config to retrieve a Token
// then generate a Client. It returns the generated Client.
func getClient(ctx context.Context, config *oauth2.Config, configFileName string) *http.Client {
cacheFile, err := tokenCacheFile(configFileName)
if err != nil {
log.Fatalf("Unable to get path to cached credential file. %v", err)
}
tok, err := tokenFromFile(cacheFile)
if err != nil {
tok = getTokenFromWeb(config)
saveToken(cacheFile, tok)
}
return config.Client(ctx, tok)
}
// getTokenFromWeb uses Config to request a Token.
// It returns the retrieved Token.
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser then type the " +
"authorization code: \n%v\n", authURL)
var code string
if _, err := fmt.Scan(&code); err != nil {
log.Fatalf("Unable to read authorization code %v", err)
}
tok, err := config.Exchange(oauth2.NoContext, code)
if err != nil {
log.Fatalf("Unable to retrieve token from web %v", err)
}
return tok
}
// tokenCacheFile generates credential file path/filename.
// It returns the generated credential path/filename.
func tokenCacheFile(filename string) (string, error) {
usr, err := user.Current()
if err != nil {
return "", err
}
tokenCacheDir := filepath.Join(usr.HomeDir, ".credentials")
os.MkdirAll(tokenCacheDir, 0700)
return filepath.Join(tokenCacheDir,
url.QueryEscape(filename)), err
}
// tokenFromFile retrieves a Token from a given file path.
// It returns the retrieved Token and any read error encountered.
func tokenFromFile(file string) (*oauth2.Token, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
t := &oauth2.Token{}
err = json.NewDecoder(f).Decode(t)
defer f.Close()
return t, err
}
// saveToken uses a file path to create a file and store the
// token in it.
func saveToken(file string, token *oauth2.Token) {
fmt.Printf("Saving credential file to: %s\n", file)
f, err := os.Create(file)
if err != nil {
log.Fatalf("Unable to cache oauth token: %v", err)
}
defer f.Close()
json.NewEncoder(f).Encode(token)
}
func main() {
// Use oauth2.NoContext if there isn't a good context to pass in.
//ctx := context.TODO()
ctx := context.Background()
b, err := ioutil.ReadFile("client_secret.json")
if err != nil {
log.Fatalf("Unable to read client secret file: %v", err)
}
// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/gmail-go-quickstart.json
sendConfig, err := google.ConfigFromJSON(b, gmail.GmailSendScope)
if err != nil {
log.Fatalf("Unable to parse client secret file to config: %v", err)
}
sendClient := getClient(ctx, sendConfig, "send.json")
sendService, err := gmail.New(sendClient)
if err != nil {
log.Fatalf("Unable to retrieve gmail Client %v", err)
}
if err := SendEmail(ctx, sendService, "jane1988#gmail.com"); err != nil {
log.Fatalf("failed to send email: %v", err)
}
}
func SendEmail(ctx context.Context, svc *gmail.Service, email string) error {
header := make(map[string]string)
header["To"] = email
header["Subject"] = "hello there"
header["MIME-Version"] = "1.0"
header["Content-Type"] = `text/html; charset="utf-8"`
header["Content-Transfer-Encoding"] = "base64"
var msg string
for k, v := range header {
msg += fmt.Sprintf("%s: %s\n", k, v)
}
msg += "\n" + "Hello, Gmail!"
gmsg := gmail.Message{
Raw: encodeWeb64String([]byte(msg)),
}
_, err := svc.Users.Messages.Send("me", &gmsg).Do()
return err
}
func encodeWeb64String(b []byte) string {
s := base64.URLEncoding.EncodeToString(b)
var i = len(s) - 1
for s[i] == '=' {
i--
}
return s[0 : i + 1]
}
This works perfectly, but without attachments. How can I attach files to the mail?
Maybe you can try change the header Content-Type to multipart/mixed (RFC 2046, Section 5.1.3) or multipart/alternative (RFC 2046, Section 5.1.4) and check how to use Content-Disposition: attachment; filename=<your file here.ext>.

Resources