I am trying to download an archived file from the Go web server. I successfully pinned the file and can unzip it from the directory of my server. The problem I am facing is serving the file and downloading it using Javascript.
Here is an overview of my code:
1) Make a request to a server that retrieves data from another endpoint
2) Structure the returned data based on the type of file the user wants (CSV (setupCSVRows) or JSON)
3) Write bytes from the buffer to the file and return the file address
4) When the user clicks on the link, make an http get request with the file address and open the contents in a new window to download
Every time I try to unzip a file, I get an error: the archive file is incomplete (with Unarchiver), and the default archive utility on the Mac shows a short download screen, then closes.
Go Code:
func ExportData(writer http.ResponseWriter, req *http.Request, session sessions.Session) (int, string) {
headers := HeaderCreation{
OriginalRequest: req,
Session: session,
}
qs := req.URL.Query()
if len(qs["collectionID"]) != 1 {
return 400, "ERROR: Must submit one collectionID in query string"
}
if len(qs["fileType"]) != 1 {
return 400, "ERROR: Must submit one fileType in query string"
}
collID := qs["collectionID"][0]
fileType := qs["fileType"][0]
url := "http://" + config.Data.Address + "/api/" + collID
response, err := httpClient.DoSystemRequest("GET", url, nil, headers)
if err != nil {
return 500, "ERROR: Could not resolve DataURL/api" + err.Error()
} else {
contents, err := ioutil.ReadAll(response.Body)
response.Body.Close()
if err != nil {
return 400, "ERROR: Response from Platform unreadable"
}
buf := new(bytes.Buffer)
w := zip.NewWriter(buf)
file, err := w.Create(collID + "." + fileType)
if err != nil {
return 400, "ERROR: Unable to create zip file with name of: " + collID + " and type of: " + fileType + "; " + err.Error()
}
switch fileType {
case "csv":
rows, err := setupCSVRows(contents)
if err != nil {
return 400, err.Error()
}
_, err = file.Write(rows)
if err != nil {
return 400, "Unable to write CSV to zip file; " + err.Error()
}
case "json":
_, err := file.Write(contents)
if err != nil {
return 400, err.Error()
}
}
err = w.Close()
if err != nil {
return 400, "ERROR: Unable to close zip file writer; " + err.Error()
}
fileAddress := collID + strconv.FormatInt(time.Now().Unix(), 10)
ioutil.WriteFile(fileAddress + ".zip", buf.Bytes(), 0777)
return 200, fileAddress
}
}
func ReturnFile(writer http.ResponseWriter, req *http.Request) {
queries := req.URL.Query()
fullFileName := queries["fullFileName"][0]
http.ServeFile(writer, req, fullFileName)
}
func setupCSVRows(contents []byte) ([]byte, error) {
var collArr interface{}
jsonErr := json.Unmarshal(contents, &collArr)
if jsonErr != nil {
return nil, errors.New("ERROR: Unable to parse JSON")
}
s := reflect.ValueOf(collArr)
var rows bytes.Buffer
var headers []string
for i := 0; i < s.Len(); i++ {
var row []string
m := s.Index(i).Interface()
m2 := m.(map[string]interface{})
for k, v := range m2 {
if i == 0 {
if k != "item_id" {
headers = append(headers, k)
}
}
if k != "item_id" {
row = append(row, v.(string))
}
}
if i == 0 {
headersString := strings.Join(headers, ",")
rows.WriteString(headersString + "\n")
}
rowsString := strings.Join(row, ",")
rows.WriteString(rowsString + "\n")
}
return rows.Bytes(), nil
}
Javascript Code:
$scope.exportCollection = function(fileType) {
$scope.exporting = true;
$scope.complete = false;
$http.get('/api/batch/export?collectionID=' + $scope.currentCollection.collectionID + '&fileType=' + fileType.toLowerCase()).success(function(data){
$scope.fileAddress = data;
}).error(function(err) {
console.log(err);
});
};
$scope.downloadFile = function() {
$http.get('/api/batch/export/files?fullFileName=' + $scope.fileAddress + ".zip")
.success(function(data) {
console.log(data);
var content = "data:application/zip;charset=utf-8," + data;
window.open(content);
})
.error(function(err) {
console.log(err);
})
}
As you can see, I tried many different URI schemes to load the file, but nothing worked.
Do I need to set the MIME type on the server side?
Any help would be greatly appreciated. Please let me know if I need to add more details.