Before we get started, please ensure you already understand the basic of REST API in GO
Let’s see the final result of this tutorial
Result
Basically when the user is click on the button, it will then trigger the javascript function downloadFile()
to make http request to the backend server in order to download the file.
Go
func DownloadFile(w http.ResponseWriter, r *http.Request) {
Openfile, err := os.Open("C://Users/User/Desktop/Download/Download.xlsx") //Open the file to be downloaded later
defer Openfile.Close() //Close after function return
if err != nil {
http.Error(w, "File not found.", 404) //return 404 if file is not found
return
}
tempBuffer := make([]byte, 512) //Create a byte array to read the file later
Openfile.Read(tempBuffer) //Read the file into byte
FileContentType := http.DetectContentType(tempBuffer) //Get file header
FileStat, _ := Openfile.Stat() //Get info from file
FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string
Filename := "demo_download"
//Set the headers
w.Header().Set("Content-Type", FileContentType+";"+Filename)
w.Header().Set("Content-Length", FileSize)
Openfile.Seek(0, 0) //We read 512 bytes from the file already so we reset the offset back to 0
io.Copy(w, Openfile) //'Copy' the file to the client
}
Explanation
- Open the file from it’s directory.
- Create a Byte variable and Read the file data
- Get the content type based on the file data by using
http.DetectContentType(< byte >)
- Get the file infomation such as size under the method
*File.Openfile.Stat()
- Define the file name and set into the Content-Type Header together with it’s content type
- Set Content-Length Header based on the file size
- Copy and response the file back to the client size by using
io.Copy(< HTTP Response >, < file >)
Javascript
function downloadFile() {
let url = "http://localhost:3000/downloadFile"
let options = {
method: 'GET',
headers: new Headers({
'Content-Type': 'application/json',
}),
mode: 'cors',
cache: 'default'
};
let strMimeType;
let strFileName;
//Perform a GET Request to server
fetch(url, options)
.then(function (response) {
let contentType = response.headers.get("Content-Type"); //Get File name from content type
strMimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
strFileName = contentType.split(";")[1];
return response.blob();
}).then(function (myBlob) {
let downloadLink = window.document.createElement('a');
downloadLink.href = window.URL.createObjectURL(new Blob([myBlob], { type: strMimeType }));
downloadLink.download = strFileName;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}).catch((e) => {
console.log("e", e);
});
}
Explanation
- Make a GET request to the server
- Get the file info like File name from the Reponse Content-Type Header
- Define the MIME type of the file. Please refer here to get the common MIME type
- Return the response in BLOB object
- Create a URL.createObjectURL() inside the window and start downloading by firing the anchor link with the method
.click()