Search code examples
csvhttpgofileserver

Download *.csv from my server


I am new to Golang and now I'm writing small app which parse some page. I got index page:

<form action="/" method='POST'>
    Enter credentials:<br>
    Login: <input type="text" name="login" >
    <br>
    Password: <input type="password" name="password" >
    <br>
    Search link:<br>
    <input type="text" name="link" >
    <br>
    <input type="submit" value="Submit">
 </form> 

So after clicking Submit button it goes to parse page (using tebeca/selenium pkg), and in the end writes data to result.csv like

func writeToCSV(users []linkedinUser) {
data := users
enc := struct2csv.New()
rows, err := enc.Marshal(data)
if err != nil {
    fmt.Printf("ERROR marshaling file, %s", err)
}
file, err := os.Create("result.csv")
if err != nil {
    fmt.Printf("ERROR creating file, %s", err)
}
defer file.Close()

writer := csv.NewWriter(file)
defer writer.Flush()

for _, value := range rows {
    err := writer.Write(value)
    if err != nil {
        fmt.Printf("ERROR writing file, %s", err)
    }
}

And in the end I got result.csv file in /home/username/go/src/parser/parsertool/src/result.csv

my main.go

func main() {
    r := mux.NewRouter()

    r.HandleFunc("/", indexHandler)
    http.Handle("/", r)

    err := http.ListenAndServe(":3000", nil) // setting listening port
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }


    func indexHandler(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("./front/index.html")
    badLoginT, _ := template.ParseFiles("./front/error.html")
    r.ParseForm()
    login := r.PostFormValue("login")
    password := r.PostFormValue("password")
    link := r.PostFormValue("link")
    if login != "" || password != "" {
        userCred := logincredentials.SetCredentials(login, password)
        if logincredentials.CheckCredentials(userCred) && link != "" {
            crawler.Crawl(link, login, password)
        } else {
            badLoginT.Execute(w, nil)
        }
    }

    t.Execute(w, nil)
}

So the main question: is there a way to get a link to download result.csv to my hard drive? The implementation isn`t important. May be in the end of writeToCSV() when result.csv is ready, window where you could choose where to save file will appear, or after getting result.csv, some link like "Click to download" will appear and after clicking you can see download window etc.

I'm stuck and really don't have any idea how to implement downloading. I would be grateful for any help.


Solution

  • On your Go server

    func main() {
      r := mux.NewRouter()
      r.HandleFunc("/", indexHandler)
      http.Handle("/", r)
      err := http.ListenAndServe(":3000", nil) // setting listening port
      if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
    
    func indexHandler(w http.ResponseWriter, r *http.Request) {
        ...
        Openfile, err := os.Open(Filename)
        FileSize := strconv.FormatInt(FileStat.Size(), 10)
        FileContentType := http.DetectContentType(FileHeader)
        //Send the headers before sending the file
        writer.Header().Set("Content-Disposition", "attachment; filename="+Filename)
        writer.Header().Set("Content-Type", FileContentType)
        writer.Header().Set("Content-Length", FileSize)
    
        //Send the file
       io.Copy(w, Openfile) 
      }
    

    In your client

    Since the file to be downloaded will be sent by the server, one need to use a js function to post the form first to the server. Then after receiving the response of the server, the download will be triggered directly by the same function.

    html

    <form>
        Enter credentials:<br>
        Login: <input id="login" type="text" name="login" >
        <br>
        Password: <input id="password" type="password" name="password" >
        <br>
        Search link:<br>
        <input id="link" type="text" name="link" >
        <br>
        <input type="button" onclick="downloadFile()">
     </form> 
    

    In a js file

    function downloadFile() {
          var data = { 
           login: document.querySelector('#login').value,
           password: document.querySelector('#password').value,
           link: document.querySelector('#link').value
           }
    
          xhttp = new XMLHttpRequest();
          xhttp.onreadystatechange = function() {
            var a;
            if (xhttp.readyState === 4 && xhttp.status === 200) {
                a = document.createElement('a');
                a.href = window.URL.createObjectURL(xhttp.response);
                // Give to file the name you wish 
                a.download = "test-file.xls";
                a.style.display = 'none';
                document.body.appendChild(a);
                a.click();
            }
        }
        }
    
        xhttp.open("POST", urlserver);
        xhttp.setRequestHeader("Content-Type", "application/json");
        // set responseType as blob for binary responses
        xhttp.responseType = 'blob';
        xhttp.send(JSON.stringify(data));