HTTP-POST file multipart - http-post

I'm trying to send a multipart form using Go packages mime/multipart and http, and I need some help to solve it.
The HTML would be:
<html>
<head><title>Multipart Test</title></head>
<body>
<form action="/multipart" enctype="multipart/form-data" method="POST">
<label for="file"> Please select a File </label>
<input id="file" type="file" name="file"/>
<br>
<label for="input1"> Please write some text </label>
<input id="input1" type="text" name="input1"/>
<br>
<label for="input2"> Please write some more text </label>
<input id="input2" type="text" name="input2"/>
<br>
<input type="submit" name="Submit" value="Submit"/>
</body>
And my Go approach is like this:
var buffer bytes.Buffer
w := multipart.NewWriter(&buffer)
// Write fields and files
w.CreateFormField("input1")
w.WriteField("input1","value1")
w.CreateFormFile("file","filename.dat")
// I need a Reader to here to read the file, but how ?
// then send the request
resp,err := http.Post(url,w.FormDataContentType(),&buffer)

The answer can be found following this sample code
// Upload file to google code
func Upload(tarball string) (err os.Error) {
// Create buffer
buf := new(bytes.Buffer) // caveat IMO dont use this for large files, \
// create a tmpfile and assemble your multipart from there (not tested)
w := multipart.NewWriter(buf)
// Create a form field writer for field label
label, err := w.CreateFormField("label")
if err != nil {
return err
}
// Write label field
label.Write([]byte("label here"))
// Create a form field writer for field summary
summary, err := w.CreateFormField("summary")
if err != nil {
return err
}
// Write summary field
summary.Write([]byte("summary here"))
// Create file field
fw, err := w.CreateFormFile("upload", tarball)
if err != nil {
return err
}
fd, err := os.Open(tarball)
if err != nil {
return err
}
defer fd.Close()
// Write file field from file to upload
_, err = io.Copy(fw, fd)
if err != nil {
return err
}
// Important if you do not close the multipart writer you will not have a
// terminating boundry
w.Close()
req, err := http.NewRequest("POST", repoUrl, buf)
if err != nil {
return err
}
req.Header.Set("Content-Type", w.FormDataContentType())
req.SetBasicAuth("email#email.com", "password")
res, err := client.Do(req)
if err != nil {
return err
}
io.Copy(os.Stderr, res.Body) // Replace this with Status.Code check
return err
}

Related

How can I use goquery parse single element

<speak><voice name=\"en-US-JennyNeural\"><prosody rate=\"1\">aaaaaaaa<break time=\"5s\"/> bbbb. <br time=\"2s\"/>ccccccdddddddd </prosody></voice></speak>
I use this code to parse and get:
doc, err := goquery.NewDocumentFromReader(strings.NewReader(text))
if err != nil {
return "", err
}
ssml, err := doc.Find("html body").Html()
if err != nil {
return "", err
}
Result:
<speak><voice name="en-US-JennyNeural"><prosody rate="1">aaaaaaaa<break time="5s"> bbbb. <br time="2s"/>ccccccdddddddd </break></prosody></voice></speak>
I think the break doesn't parse Correctly. I want to parse <break/> like <br/>.
Assuming you're using github.com/PuerkitoBio/goquery, it uses golang.org/x/net/html under the hood for HTML parsing, which is an HTML5-compliant tokenizer and parser.
<br> and <break> are parsed differently because in HTML <br> is a tag that must not have a closing tag, but <break> is not such a tag.
If you want goquery to handle your HTML properly, you must use an explicit closing tag for <break> instead of the self-closing tag.
E.g. instead of this:
<break time="5s"/>
You must use this:
<break time="5s"></break>
With this change your output will be (try it on the Go Playground):
<speak><voice name="en-US-JennyNeural"><prosody rate="1">aaaaaaaa<break time="5s"></break> bbbb. <br time="2s"/>ccccccdddddddd </prosody></voice></speak>
d := xml.NewDecoder(strings.NewReader(text))
var writer bytes.Buffer
e := xml.NewEncoder(&writer)
for {
t, err := d.Token()
if err == io.EOF {
break
}
if err != nil {
return "", err
}
if t == nil {
break
}
switch se := t.(type) {
case xml.StartElement:
e.EncodeToken(se)
case xml.EndElement, xml.CharData, xml.Comment, xml.ProcInst, xml.Directive:
e.EncodeToken(se)
}
}
e.Flush()
return writer.String(), nil

How to execute multiple variables in HTML Go Template?

I've tried looking at the other questions, and they don't seem to help my situation.
I essentially need to have 2 if statements on my HTML page, but whenever I trigger the second tmpl.Execute() I essentially get the same page embedded within those if statements.
Here is a function that I am trying to get working:
func RemoveVehicle(w http.ResponseWriter, r *http.Request) {
conditionsMap := map[string]interface{}{}
username, _ := ExtractTokenUsername(r)
if username != "" {
conditionsMap["Username"] = username
}
t, err := template.ParseFiles("remove.html")
if err != nil {
http.Error(w, err.Error(), 500)
return
}
if r.Method != http.MethodPost {
t.Execute(w, conditionsMap) //Here I am trying to check to see if the user is logged in, and if not to return a false boolean that will trigger the else statement
return
}
db, err := sql.Open("mysql", "root:*******#tcp(127.0.0.1:3306)/my_db")
if err != nil {
fmt.Println("Connection Failed.")
panic(err.Error())
}
defer db.Close()
var car Vehicle
sqlStatement := `SELECT * FROM Vehicle`
rows, err := db.Query(sqlStatement)
if err != nil {
panic(err)
}
defer rows.Close()
var carSlice []Vehicle
for rows.Next() {
rows.Scan(&car.Id, &car.Date, &car.Brand, &car.Model, &car.Mileage, &car.Year, &car.rented, &car.Dayrate)
carSlice = append(carSlice, car)
}
if r.Method != http.MethodPost {
t.Execute(w, carSlice) // Then here I am trying to populate the form select with a few rows from a table
return
}
var id_ = r.FormValue("select")
fmt.Println(id_)
stmt, e := db.Prepare("DELETE FROM vehicle WHERE id=?")
ErrorCheck(e)
stmt.Exec(id_)
}
I have commented out the 2 parts that I am trying to get working simultaneously, but they work individually.
Here is the relevant HTML:
{{if .Username}}
<div><img src="images/kogdpilnmzhz9rhzceo2.png" alt="" width="65" height="65" class="addV_label"/></div>
<hr style="height:5px">
<form action="/remove" method="POST" source="custom" name="form">
<input type="hidden" name="xss-token" value=""/>
<div class="form-group">
<div>
<label class="addV_label">Select Vehicle </label>
<select name="select" class="form-control loginInput2" required="required">
{{range .}}
<option value="{{.Id}}">{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | £{{.Dayrate}}/pd</option>
{{end}}
</select>
</div>
</div>
<div>
<button class="btn-block frgt_1 btn addV_btn" type="submit" value="remove">REMOVE</button>
</div>
</form>
{{else}}
<p> Access Denied, please login.Login</p>
{{end}}
I've tried to use a struct, but the carSlice is already a struct and conditionMap is a map.
What would be the best solution to tackling this situation?
First off, it is recommended to initialize the *template.Template types and the *sql.DB connection pool only once, during program start up. Both types are safe for concurrent use and can therefore be used by multiple handlers simultaneously.
var (
removeTemplate *template.Template
db *sql.DB
)
func init() {
var err error
removeTemplate, err = template.ParseFiles("remove.html")
if err != nil {
panic(err)
}
db, err = sql.Open("mysql", "root:*******#tcp(127.0.0.1:3306)/my_db")
if err != nil {
panic(err)
} else if err := db.Ping(); err != nil {
panic(err)
}
}
Now your handler can look something like the following:
func RemoveVehicle(w http.ResponseWriter, r *http.Request) {
// check if the user is logged in
username, _ := ExtractTokenUsername(r)
if len(username) == 0 {
// if not, render the template with no data, this
// will show the "please login" part of your template
if err := removeTemplate.Execute(w, nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
return
}
switch r.Method {
// if the method is GET, show the list of vehicles available
case http.MethodGet:
// select vehicles from db
rows, err := db.Query(`SELECT * FROM Vehicle`)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer rows.Close()
// scan rows
var vehicles []Vehicle
for rows.Next() {
var v Vehicle
err := rows.Scan(&v.Id, &v.Date, &v.Brand, &v.Model, &v.Mileage, &v.Year, &v.rented, &v.Dayrate)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
vehicles = append(vehicles, v)
}
if err := rows.Err(); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// now render the template with the data
// that you just retrieved from the database
data := map[string]interface{}{
"Username": username,
"Vehicles": vehicles,
}
if err := removeTemplate.Execute(w, data); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
// if the method is POST, delete the vehicle
case http.MethodPost {
var id = r.FormValue("select")
if _, err := db.Exec("DELETE FROM vehicle WHERE id=?", id); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
And in your template, since a data passed in by the handler is a map with Username and Vehicles keys, you need to range over .Vehicles and not just the ..
{{if .Username}}
<div><img src="images/kogdpilnmzhz9rhzceo2.png" alt="" width="65" height="65" class="addV_label"/></div>
<hr style="height:5px">
<form action="/remove" method="POST" source="custom" name="form">
<input type="hidden" name="xss-token" value=""/>
<div class="form-group">
<div>
<label class="addV_label">Select Vehicle </label>
<select name="select" class="form-control loginInput2" required="required">
{{range .Vehicles}}
<option value="{{.Id}}">{{.Brand}} {{.Model}} ({{.Year}}), {{.Mileage}} miles | £{{.Dayrate}}/pd</option>
{{end}}
</select>
</div>
</div>
<div>
<button class="btn-block frgt_1 btn addV_btn" type="submit" value="remove">REMOVE</button>
</div>
</form>
{{else}}
<p> Access Denied, please login.Login</p>
{{end}}

golang: can't execute t.execute

I'm trying to make an Handler to update one row each time getting data from a submitt button,
here is my code:
func RowHandler(res http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
http.ServeFile(res, req, "homepage.html")
return
}
Person_id := req.FormValue("Person_id")
stmt, err := db.Prepare("update Cityes set Status='right' where Person_id=?")
if err != nil {
log.Print("error ", err)
}
_, err = stmt.Exec(&Person_id)
t, err := template.ParseFiles("city_update.html") //hier i just want to show a text in html Page
if err != nil {
log.Fatal(err)
}
err = t.Execute(res, "/city_update")
}
Here instead of following
err = t.Execute(res, "/city_update")
pass data to be used to fill your template as send arguement to Execute not string. link to doc
For example .
err = t.Execute(res,struct{ID string}{Person_id})

Multipart file field is unreadable

I am trying to upload photos to Twitter. I created a multipart writer and creating a file field using that named media but when I send my request to Twitter it keeps responding missing media field.
Am I missing something?
Here is my code
f, err := os.Open("/Users/nikos/Desktop/test.png")
errored:
if nil != err {
fmt.Println(err)
return
}
var img = new(bytes.Buffer)
enc := base64.NewEncoder(base64.StdEncoding, img)
_, err = io.Copy(enc, f)
if nil != err {
goto errored
}
body := new(bytes.Buffer)//Multipart body
writer := multipart.NewWriter(body)
cl, err := twitter.OauthClient.MakeHttpClient(&oauth.AccessToken{
Token: "xxx",
Secret: "yyy",
})
err = writer.WriteField("media_data", img.String())//base64 version of the image (i tried both binary and base64 versions neither will work)
if nil != err {
goto errored
}
part, err := writer.CreateFormFile("media", "test.png")//actual binary file multiparted and it is named media.
if nil != err {
goto errored
}
_, err = io.Copy(part, f)
if nil != err {
goto errored
}
req, err := http.NewRequest("POST",
"https://upload.twitter.com/1.1/media/upload.json",
body)
if nil != err {
goto errored
}
res, err := cl.Do(req)
if nil != err {
goto errored
}
//and twitter responds that there is no field attached named media
_, err = io.Copy(os.Stdout, res.Body)
fmt.Println(res)
if nil != err {
goto errored
}
Updates: Just referred Twitter API Upload parameter. As per your code snippet you're using both fields media and media_data. You have to use only one -
Upload using base64 -> field name is media_data
Upload using raw -> field name is media
And, you have to add Content-Type header.
req, err := http.NewRequest("POST",
"https://upload.twitter.com/1.1/media/upload.json",
body)
req.Header.Set("Content-Type", writer.FormDataContentType())
if err := writer.Close(); err != nil {
log.Println(err)
}
// Now fire the http request
PS: While composing an answer, in 30 secs gap, #cerise-limón added comment, also close the multipart writer as mentioned by #cerise-limón.
Asked in the comment:
Twitter accepts application/octet-stream, you may not need below approach.
Adding multi-part with user supplied Content-Type instead of application/octet-stream. Basically you have to do same implementation as convenience wrapper with your content-type.
writer := multipart.NewWriter(body)
h := make(textproto.MIMEHeader)
h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
escapeQuotes(fieldname), escapeQuotes(filename)))
h.Set("Content-Type", "image/png")
part, err := writer.CreatePart(h)
// use part same as before
Definition of escapeQuotes from multiple-part package.
var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
func escapeQuotes(s string) string {
return quoteEscaper.Replace(s)
}

Golang how can I get full file path

I been searching around and can not find a way to get the full file path in Go . I have a regular html form and then I try to get all the information in the backend
<form method="post" enctype="multipart/form-data" action="/uploads">
<p><input type="file" name="my file" id="my file"></p>
<p>
<input type="submit" value="Submit">
</p>
func upload() {
f,h,err := r.FormFile("my file")
if err != nil {
log.Println(err)
http.Error(w,"Error Uploading",http.StatusInternalServerError)
return
}
defer f.Close()
println(h.Filename)
}
// This gets me the name of the file, I would like the full path of it
I have tried file path.dir() but that does not do anything
here is an example:
package main
import (
"fmt"
"path/filepath"
)
func main() {
abs,err := filepath.Abs("./hello.go")
if err == nil {
fmt.Println("Absolute:", abs)
}
}
As far as I know, you cannot get the filepath form the f value in your code. Because the file data is not stored in disk yet.
And you want to store the file to a path, you can do it this way.
f,h,err := r.FormFile("myfile")
if err != nil{
log.Println("err: ",err)
http.Error(w,"Error Uploading",http.StatusInternalServerError)
return
}
defer f.Close()
fmt.Println("filename: ",h.Filename)
bytes, err := ioutil.ReadAll(f)
if err != nil {
fmt.Println(err)
}
filepath := "./aa" //set your filename and filepath
err = ioutil.WriteFile("aa", bytes, 0777)
if err != nil {
fmt.Println(err)
}

Resources