upload file with same format using beego - file-upload

File Uploading is done but not with the same name as filename
i have tried this in html file
<html>
<title>Go upload</title>
<body>
<form action="http://localhost:8080/receive" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file">
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
and in beego/go receive.go
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func uploadHandler(w http.ResponseWriter, r *http.Request) {
// the FormFile function takes in the POST input id file
file, header, err := r.FormFile("file")
if err != nil {
fmt.Fprintln(w, err)
return
}
defer file.Close()
out, err := os.Create("/home/vijay/Desktop/uploadfile")
if err != nil {
fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
return
}
defer out.Close()
// write the content from POST to the file
_, err = io.Copy(out, file)
if err != nil {
fmt.Fprintln(w, err)
}
fmt.Fprintf(w, "File uploaded successfully : ")
fmt.Fprintf(w, header.Filename)
}
func main() {
http.HandleFunc("/", uploadHandler)
http.ListenAndServe(":8080", nil)
}
i am able to achieve uploading file here with same format... but not with the same name..
now i want this file to be uploaded with same name as file name

You are not using a Beego controller to handle the upload
package controllers
import (
"github.com/astaxie/beego"
)
type MainController struct {
beego.Controller
}
function (this *MainController) GetFiles() {
this.TplNames = "aTemplateFile.html"
file, header, er := this.GetFile("file") // where <<this>> is the controller and <<file>> the id of your form field
if file != nil {
// get the filename
fileName := header.Filename
// save to server
err := this.SaveToFile("file", somePathOnServer)
}
}

Related

Golang - Sending API POST Request - Not enough arguments error

The following code attempts to send a POST API request with a payload that is in RequestDetails.FormData. When I run main.go function, then I get the following errors.
go run main.go
# command-line-arguments
./main.go:53:17: not enough arguments in call to http.HandleFunc
./main.go:53:33: not enough arguments in call to reqDetails.Send
have ()
want (http.ResponseWriter, *http.Request)
./main.go:53:33: reqDetails.Send() used as value
The code is available below. Anybody knows what I could do wrong here? Thanks a lot for your help.
//main.go
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
)
// RequestDetails contains input data for Send
type RequestDetails struct {
EndPoint string
FormType string
FormData map[string]string
}
// Send sends API POST request to an endpoint
func (rd RequestDetails) Send(w http.ResponseWriter, r *http.Request) {
json_data, err := json.Marshal(rd.FormData)
if err != nil {
log.Fatal(err)
}
resp, err := http.Post(rd.EndPoint, rd.FormType, bytes.NewBuffer(json_data))
if err != nil {
log.Fatal(err)
}
fmt.Println(resp)
}
func main() {
m := map[string]string{
"AuthParamOne": "AP0000001",
"AuthParamTwo": "AP0000002",
"AuthParamThree": "AP0000003",
}
reqDetails := RequestDetails{
EndPoint: "https://httpbin.org/post",
FormType: "application/json",
FormData: m,
}
http.HandleFunc(reqDetails.Send())
}
you have to use HandleFunc in following below:
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
for code above follow this:
http.HandleFunc("/test",reqDetails.Send) //-> add reference instead of calling 'reqDetails.Send()'
reference: https://pkg.go.dev/net/http#HandleFunc
please vote up :)
In your Send method, you don't make use of w http.ResponseWriter, r *http.Request, So it seems you don't need them:
func (rd RequestDetails) Send() {...
Also in your last line, HandleFunc requires different arguments which once again is not necessary in your case. Just try to run the Send method:
reqDetails.Send()
The whole main.go file:
//main.go
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
)
// RequestDetails contains input data for Send
type RequestDetails struct {
EndPoint string
FormType string
FormData map[string]string
}
// Send sends API POST request to an endpoint
func (rd RequestDetails) Send() {
json_data, err := json.Marshal(rd.FormData)
if err != nil {
log.Fatal(err)
}
resp, err := http.Post(rd.EndPoint, rd.FormType, bytes.NewBuffer(json_data))
if err != nil {
log.Fatal(err)
}
fmt.Println(resp)
}
func main() {
m := map[string]string{
"AuthParamOne": "AP0000001",
"AuthParamTwo": "AP0000002",
"AuthParamThree": "AP0000003",
}
reqDetails := RequestDetails{
EndPoint: "https://httpbin.org/post",
FormType: "application/json",
FormData: m,
}
reqDetails.Send()
}
if your code like this
watcher := bufio.NewReader(os.Stdin)
input, _ := watcher.ReadString()
fmt.Println(input)
you needed this for reading line line
old -> input, _ := watcher.ReadString()
new -> input, _ := watcher.ReadString('\n')

Rest API in Go (Consume and host)

I am trying to request something, like a book by its id, and then host it locally so that if I write my local URL, like http://localhost:8080​/books?books=<book-id> it would show me the specific result.
To try to be concrete, I need to connect the two. Get the information from that URL, so "consume" and also host it locally, specifically by ID. I am not sure how to do both at once.
To create the paths, I've been using gorilla mux
So separately, I've used this, which would give me all the books at once (URL is not real).
func main() {
response, err := http.Get("https://bookibook.herokuapp.com/books/")
if err != nil {
fmt.Printf("there is no book with this ID %s\n", err)
} else {
data, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(data))
}
}
and then this, which would create a local path for http://localhost:8080/books/ID
import (
"fmt"
"github.com/gorilla/mux"
"log"
"net/http"
)
func getID(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
fmt.Fprintf(w, "Get id %s\n", vars["id"])
}
func main() {
// Configure routes.
router := mux.NewRouter()
router.HandleFunc("/books/{id}/", getID).Methods(http.MethodGet)
// Start HTTP server.
if err := http.ListenAndServe(":8080", router); err != nil {
log.Fatal(err)
}
}

How can I see or test graceful restarts in Go?

I serve HTTP over gin's https://github.com/fvbock/endless. I would like to see the differences from the basic HTTP server.
I've sent syscall.SIGUSR1 signal with:
syscall.Kill(getPid(), syscall.SIGUSR1)
The app doesn't exit, but I cannot detect the restart.
What I have to do is initialise new configurations to the app when the toml config file changes.
My code is as follows:
package main
import (
"os"
"fmt"
"syscall"
"github.com/gin-gonic/gin"
"github.com/fvbock/endless"
"github.com/BurntSushi/toml"
)
type Config struct {
Age int
Cats []string
}
var cfg Config
func restart(c *gin.Context) {
syscall.Kill(os.Getpid(), syscall.SIGUSR1)
}
func init() {
toml.DecodeFile("config.toml", &cfg)
fmt.Println("Testing", cfg)
}
func main() {
router := gin.New()
router.GET("/restart", restart)
if err := endless.ListenAndServe("localhost:7777", router); err != nil {
panic(err)
}
}
When I hit the restart endpoint, I want the toml config printed out.
Updating answer based on the changes to your question. The endless library can allow you to handle that signal by default. You will need to register a hook. I've expanded on your example code below:
package main
import (
"os"
"fmt"
"syscall"
"github.com/gin-gonic/gin"
"github.com/fvbock/endless"
"github.com/BurntSushi/toml"
)
type Config struct {
Age int
Cats []string
}
var cfg Config
func restart(c *gin.Context) {
syscall.Kill(os.Getpid(), syscall.SIGUSR1)
}
func readConfig() {
toml.DecodeFile("config.toml", &cfg)
fmt.Println("Testing", cfg)
}
func main() {
readConfig()
router := gin.New()
router.GET("/restart", restart)
srv := endless.NewServer("localhost:7777", router)
srv.SignalHooks[endless.PRE_SIGNAL][syscall.SIGUSR1] = append(
srv.SignalHooks[endless.PRE_SIGNAL][syscall.SIGUSR1],
readConfig)
if err := srv.ListenAndServe(); err != nil {
panic(err)
}
}
Now when you call the restart endpoint, you should see the changes to config file refelcted in stdout. However in order to watch the file for changes you would need to use something like fsnotify

How to use Golang's github.com/google/google-api-go-client/customsearch/v1

I've done the Oauth callback from which people said it's not needed, and just needs the cx code but I have yet to figure out how to add the cx parameter to the call.
package main
import (
"fmt"
"log"
"github.com/vinniyo/authCallback"
"github.com/google/google-api-go-client/customsearch/v1"
)
func main() {
client, err := authCallback.BuildOAuthHTTPClient()
if err != nil {
log.Fatalf("Error building OAuth client: %v", err)
}
service, err := customsearch.New(client)
if err != nil {
log.Fatalf("Error creating YouTube client: %v", err)
}
fmt.Println(service.Cse.List("bob").Do())
}
I know to upload a video to youtube you add parameters before do() but how do you figure out the formatting? eg:
upload := &youtube.Query{
Status: &youtube.VideoStatus{PrivacyStatus: *privacy},
}
The CseListCall struct has Cx method which lets you add that parameter: https://godoc.org/google.golang.org/api/customsearch/v1#CseListCall
fmt.Println(service.Cse.List("bob").Cx("my_cx_id").Do())

golang server upload file response net::ERR_EMPTY_RESPONSE

I am uploading a small audio file to server using DART + golang. Everything kinda works fine, until I POST and go doesn't return anything. I would like to return filename so I can change the label text on the input.
1) GOLANG:
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"time"
"fmt"
"os"
"io"
)
http.HandleFunc("/upload", webUploadHandler)
[...]
func webUploadHandler(w http.ResponseWriter, r *http.Request) {
file, header, err := r.FormFile("file") // the FormFile function takes in the POST input id file
defer file.Close()
if err != nil {
fmt.Fprintln(w, err)
return
}
out, err := os.Create("/tmp/uploadedfile")
if err != nil {
fmt.Fprintf(w, "Unable to create the file for writing. Check your write access privilege")
return
}
defer out.Close()
// write the content from POST to the file
_, err = io.Copy(out, file)
if err != nil {
fmt.Fprintln(w, err)
}
fmt.Fprintf(w,"File uploaded successfully : ")
fmt.Fprintf(w, header.Filename)
}
2) DART response, alert
window.alert("upload complete");
works
3) ERROR in Chromium Console:
POST http://localhost:9999/upload net::ERR_EMPTY_RESPONSE
I'm quite new to GOLANG so any help will me much appreciated.
First error in the code above:
defer file.Close()
was before checking
if err != nil
-- UPDATE
and missing part 2, in DART:
req.setRequestHeader("Content-type","multipart/form-data");