How to upload files with Golang and Ajax?
Tags: go, ajax, fileupload
Published: 2017-08-16 17:00:16

---
title: "How to upload files with Golang and Ajax?"
published: true
description: File upload
tags: golang,ajax,file-upload
---

Uploading file(s) is a common functionality that we want to use in our websites, it could be for user's profile avatar, an image gallery, a cover post and so on, but What if you want to do it by using Ajax. Let's see how  I solved this problem.


First of all let me give you the project structure:
```
public\
    api.js
    app.js
    index.html
    style.css
controllers\
    file.go
files\
```

Then let's create the `index.html` file inside `public` folder and write the following code:

```html
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, 
    user-scalable=no, initial-scale=1.0, maximum-scale=1.0,
minimum-scale=1.0">
    <link rel="stylesheet" 
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="styles.css">
    <title>File upload using Ajax</title>
</head>
<body>
    <form action="/upload" method="post" enctype="multipart/form-data" class="uploadForm">
        <input class="uploadForm__input" type="file" name="file" id="inputFile" accept="image/*">
        <label class="uploadForm__label" for="inputFile">
            <i class="fa fa-upload uploadForm__icon"></i> Select a file
        </label>
    </form>
    <div class="notification" id="alert"></div>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="api.js"></script>
    <script src="app.js"></script>
</body>
</html>
```

Let's add some basic CSS styles and create the `styles.css` file inside `public` folder:
```css
	
body {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100vh;    
    font-family: Verdana, Geneva, Tahoma, sans-serif;
}

body,
.uploadForm,
.uploadForm__label {
    display: flex;
    align-items: center;
    justify-content: center;
}

.uploadForm {
    width: 600px;
    max-width: 600px;
    height: 300px;
    flex-direction: column;    
    border: 2px dashed gray;
    font-family: inherit;
}

.uploadForm__input {
    display: none;
}

.uploadForm__label {
    border: 1px solid gray;
    padding: .5em 2em;
    color: deepskyblue;
    transition: transform .4s;
    flex-direction: column;
}

.uploadForm__label:hover {
    cursor: pointer;
    transform: scale(1.01);
    box-shadow: grey 2px 2px 10px;
}

.uploadForm__icon {
    font-size: 1.8em;
}

.notification {    
    display: none;    
}

.success,
.error {
    right: 30px;
    z-index: 10;
    width: 300px;
    bottom: 40px;
    padding: 1em;
    height: auto;
    text-align: center;
    display: block;
    position: fixed;
    font-family: inherit;
    animation: alert .8s forwards;
}

.notification.success {
    background: #D9EDF7;
    color: #31709C;
}

.notification.error {
    background: #F2DEDE;
    color: #B24842;
}

@keyframes alert {
    0% {
        opacity: 0;
        bottom: -40px;
    }

    100% {
        opacity: 1;
        bottom: 40px;
    }
}
```

Next let's create the `app.js` file inside `public` folder too and write the following code:

```javascript
(function (d, axios) {
    "use strict";
    var inputFile = d.querySelector("#inputFile");
    var divNotification = d.querySelector("#alert");

    inputFile.addEventListener("change", addFile);

    function addFile(e) {
        var file = e.target.files[0]
        if(!file){
            return
        }
        upload(file);
    }

    function upload(file) {
        var formData = new FormData()
        formData.append("file", file)
        post("/upload", formData)
            .then(onResponse)
            .catch(onResponse);        
    }
    
    function onResponse(response) {
        var className = (response.status !== 400) ? "success" : "error";
        divNotification.innerHTML = response.data;
        divNotification.classList.add(className);
        setTimeout(function() {
            divNotification.classList.remove(className);
        }, 3000);
    }
})(document, axios)
```

Finally we need to create `api.js` file one more time inside `public` folder and write this code:

```javascript
"use strict";

function post(url, data) {
    return axios.post(url, data)
        .then(function (response) {
            return response;
        }).catch(function (error) {
            return error.response;
        });
}
```

Well, after all this let's finally write some `Go` code. I'm going to start by creating the `file.go` file inside `controllers` folder and write the following:

```go
package controllers

import (
	"fmt"
	"io/ioutil"
	"mime/multipart"
	"net/http"
)

// UploadFile uploads a file to the server
func UploadFile(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		http.Redirect(w, r, "/", http.StatusSeeOther)
		return
	}

	file, handle, err := r.FormFile("file")
	if err != nil {
		fmt.Fprintf(w, "%v", err)
		return
	}
	defer file.Close()

	mimeType := handle.Header.Get("Content-Type")
	switch mimeType {
	case "image/jpeg":
		saveFile(w, file, handle)
	case "image/png":
		saveFile(w, file, handle)
	default:
		jsonResponse(w, http.StatusBadRequest, "The format file is not valid.")
	}
}

func saveFile(w http.ResponseWriter, file multipart.File, handle *multipart.FileHeader) {
	data, err := ioutil.ReadAll(file)
	if err != nil {
		fmt.Fprintf(w, "%v", err)
		return
	}

	err = ioutil.WriteFile("./files/"+handle.Filename, data, 0666)
	if err != nil {
		fmt.Fprintf(w, "%v", err)
		return
	}
	jsonResponse(w, http.StatusCreated, "File uploaded successfully!.")
}

func jsonResponse(w http.ResponseWriter, code int, message string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	fmt.Fprint(w, message)
}
```

As our final step let's create the `main.go` file in your root directory and use the `file package` like so:

```go
package main

import (
	"log"
	"net/http"
        
        // Note this is my path according to my GOPATH, chage it according to yours.
	"bitbucket.org/gustavocd/upload-img/controllers"
)

func main() {
	http.Handle("/", http.FileServer(http.Dir("./public")))
	http.HandleFunc("/upload", controllers.UploadFile)
	log.Println("Running")
	http.ListenAndServe(":8080", nil)
}
```

## Notes
1. I'm not handling validation (you should do it), but it should work like a charm.
2. I'm using my `GOPATH` root, please change according to yours.
3. Keep learning and happy code :).