Saturday, 21 November 2020

golang 22 ionic react download file from server

access server directory by phone 
open static folder -> press file name -> press download icon

file starts downloading to phone browser, progress is shown

download complete, file is saved in phone download folder
//main.go
package main

import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"path"
"path/filepath"
"runtime"
"sort"
"strconv"
"strings"

"github.com/gorilla/mux"
)

type fileStruct struct {
Name  string
IsDir bool
Size  int64
}

var projectPath = rootDir() + "\\golang12\\"

func indexGetHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("index get")
dir := viewDirectory(projectPath)

w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(dir)
}

func indexPostHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("index post")
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusCreated)

r.ParseForm()
path := r.PostForm.Get("dir")
dir := viewDirectory(path)

json.NewEncoder(w).Encode(dir)
}

func downloadPostHandler(w http.ResponseWriter, r *http.Request) {
fmt.Println("download post")
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.WriteHeader(http.StatusCreated)

r.ParseForm()
dir := r.PostForm.Get("dir")
dirSlash := strings.Replace(dir, "\\", "/", -1)
_, filename := path.Split(dirSlash)

fmt.Println(dir,)
w.Header().Set("Content-Disposition", "attachment; filename="+strconv.Quote(filename))

file, err := os.Open(dir)
if err != nil {
log.Fatal(err)
}
defer file.Close()

fi, err := file.Stat()
if err != nil {
log.Fatal(err)
}

w.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10))

io.Copy(w, file)
}

func rootDir() string {
_, b, _, _ := runtime.Caller(0)
d := path.Join(path.Dir(b))
return filepath.Dir(d)
}

func viewDirectory(dirname string) []fileStruct {
f, err := os.Open(dirname)
if err != nil {
//log.Fatal(err)
return []fileStruct{}
}
files, err := f.Readdir(-1)
f.Close()
if err != nil {
//log.Fatal(err)
return []fileStruct{}
}

var dir = []fileStruct{}
for _, file := range files {
name := dirname + file.Name()
var size int64 = 10000000
if !file.IsDir() {
size = file.Size()
}

dir = append(dir, fileStruct{
Name:  name,
IsDir: file.IsDir(),
Size:  size,
})
}

sort.SliceStable(dir, func(i, j int) bool {
return dir[i].Name < dir[j].Name
})

return dir
}

func main() {
r := mux.NewRouter()
r.HandleFunc("/", indexGetHandler).Methods("GET")
r.HandleFunc("/", indexPostHandler).Methods("POST", "OPTIONS")
r.HandleFunc("/download/", downloadPostHandler).Methods("POST", "OPTIONS")
fs := http.FileServer(http.Dir("./static/"))
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))
http.Handle("/", r)
http.ListenAndServe(":8000", nil)
}

-----------------------------------
//folderDisplay.js
import React, { useState } from 'react';
import { folder, folderOpenOutline, documentOutline, cloudUploadOutline, cloudDownloadOutline } from 'ionicons/icons';
import { IonIcon } from '@ionic/react';
import axios from 'axios'
import '../pages/Home.css'
import saveAs from 'file-saver';
const qs = require('querystring')

export default function FolderDisplay(props) {
    const [open, setOpen] = useState(false)
    const [subDir, setSubDir] = useState([])
    const [showLoad, setShowLoad] = useState(false)
    const [downlaodProgress, setDownloadProgress] = useState(0)

    function post_dir(d) {
        axios({
            method: 'post',
            url: 'http://192.168.0.18:8000/',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            data: qs.stringify({ dir: d })
        })
            .then(response => {
                setSubDir(response.data)
            })
            .catch(function (error) {
                alert(error);
            });
    }

    function download_dir(d, name) {
        axios({
            method: 'post',
            url: 'http://192.168.0.18:8000/download/',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            data: qs.stringify({ dir: d }),
            responseType: 'blob',  // important

            onDownloadProgress: progressEvent => {
                const p = parseInt(progressEvent.loaded / props.size * 100);
                setDownloadProgress(p)
            },
        })
            .then(response => {
                console.log(response)
                saveAs(response.data, name);
            })
            .catch(function (error) {
                alert(error);
            });
    }

    function clickEvent() {
        setShowLoad(!showLoad)

        if (!props.isDir) { return }

        if (!open) {
            post_dir(props.dir)
        }

        setOpen(!open)
    }

    function downloadEvent() {
        download_dir(props.dir, props.name)
    }

    const folder_icon = open ? <IonIcon icon={folderOpenOutline} /> : <IonIcon icon={folder} />

    const sub_folder_list = subDir.map((item, index) => {
        const dir_split = item.Name.split("\\")
        const folder_name = dir_split[dir_split.length - 1].replace(props.name, '')
        const dir_name = item.Name.replace(folder_name, '') + '\\' + folder_name
        return <li>
            <FolderDisplay name={folder_name} dir={dir_name} isDir={item.IsDir} size={item.Size} />
        </li>
    })

    return (
        <li >
            <span onClick={() => clickEvent()}>
                {props.isDir ? folder_icon : <IonIcon icon={documentOutline} />}{' '}
                {props.name}{' '}
                {showLoad && props.isDir ? <IonIcon icon={cloudUploadOutline} /> : null}{' '}
                {showLoad && !props.isDir ? <IonIcon icon={cloudDownloadOutline} onClick={() => downloadEvent()} /> : null}{' '}
                {downlaodProgress != 0 ? downlaodProgress + '%' : null}
            </span>
            {open ? <ul class="no-bullets">
                {sub_folder_list}
            </ul> : null}
        </li>
    );
};

No comments:

Post a Comment