├── .gitignore ├── .gitattributes ├── modules ├── utils.go ├── pages.go └── api.go ├── app.json ├── html ├── index.html └── upload.html ├── main.go ├── go.mod ├── README.md ├── .github └── workflows │ └── main.yml └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | downloads 2 | FileServer 3 | FileServer.exe -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /modules/utils.go: -------------------------------------------------------------------------------- 1 | package modules 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | func RandomString(count int) string { 9 | rand.Seed(time.Now().UnixNano()) 10 | letters := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 11 | b := make([]rune, count) 12 | for i := range b { 13 | b[i] = letters[rand.Intn(len(letters))] 14 | } 15 | return string(b) 16 | } -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "File Server", 3 | "description": "An app that can store files in your server and get links for files", 4 | "repository": "https://github.com/AnjanaMadu/FileServer", 5 | "logo": "https://img.icons8.com/color/48/000000/database-restore.png", 6 | "env": { 7 | "GOVERSION": { 8 | "description": "Dont change this.", 9 | "value": "1.17" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | File Server 7 | 8 |

Welcome to File Server v0.1

9 |

10 | This is a simple file server that allows you to upload files to the server. 11 |
12 | You can upload files to the server and then download them. 13 |

14 |

Go to Uploads page to upload files!

15 | 16 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | 6 | "FileServer/modules" 7 | 8 | "github.com/labstack/echo/v4" 9 | ) 10 | 11 | func main() { 12 | // Initalize 13 | e := echo.New() 14 | port := os.Getenv("PORT") 15 | os.Mkdir("downloads", os.ModePerm) 16 | 17 | // Routes 18 | e.GET("/", modules.IndexPage) 19 | e.GET("/upload", modules.UploadPage) 20 | e.POST("/api/upload", modules.HandleUpload) 21 | e.GET("/dl/id/:id", modules.DownloadFile) 22 | e.GET("/dl/name/:name", modules.DownloadFile) 23 | e.GET("/files", modules.GetFiles) 24 | 25 | // Start server 26 | e.Logger.Fatal(e.Start(":" + port)) 27 | } 28 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module FileServer 2 | 3 | go 1.17 4 | 5 | require github.com/labstack/echo/v4 v4.6.3 6 | 7 | require ( 8 | github.com/labstack/gommon v0.3.1 // indirect 9 | github.com/mattn/go-colorable v0.1.12 // indirect 10 | github.com/mattn/go-isatty v0.0.14 // indirect 11 | github.com/valyala/bytebufferpool v1.0.0 // indirect 12 | github.com/valyala/fasttemplate v1.2.1 // indirect 13 | golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 // indirect 14 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect 15 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect 16 | golang.org/x/text v0.3.7 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /modules/pages.go: -------------------------------------------------------------------------------- 1 | package modules 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "net/http" 8 | "strings" 9 | 10 | "github.com/labstack/echo/v4" 11 | ) 12 | 13 | func IndexPage(c echo.Context) error { 14 | return c.File("html/index.html") 15 | } 16 | 17 | func UploadPage(c echo.Context) error { 18 | return c.File("html/upload.html") 19 | } 20 | 21 | func GetFiles(c echo.Context) error { 22 | flist := make([]string, 0) 23 | files, err := ioutil.ReadDir("downloads") 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | for _, f := range files { 28 | ahref := fmt.Sprintf("%s", f.Name(), f.Name()) 29 | flist = append(flist, ahref) 30 | } 31 | return c.HTML(http.StatusOK, fmt.Sprintf("

Files

%s

", strings.Join(flist, "
"))) 32 | } 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🗄 FileServer 2 | 3 | **This is a simple file server that allows you to upload files to the server.** 4 |
5 | You can upload files to the server and then get download links to them. 6 | 7 | - _If you using heroku, After heroku restarts all files will be deleted!_ 8 | 9 | ## Deploy 10 | **Deploy to Heroku** 11 | 12 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/AnjanaMadu/FileServer) 13 | 14 | ----- 15 | **Deploy to VPS** 16 | 17 | _Steps:_ 18 | - Install go in your server. 19 | - Clone repo. `git clone https://github.com/AnjanaMadu/FileServer && cd FileServer` 20 | - Install libs. `go mod tidy` 21 | - Build app. `go build` 22 | - Grant premissions. `chmod +x FileServer` 23 | - Run app. `./FileServer` 24 | 25 | 26 | ## Credits 27 | - [**Me**](https://github.com/AnjanaMadu) 28 | - [**Echo**](https://github.com/labstack/echo/) web framework 29 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: CI 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Allows you to run this workflow manually from the Actions tab 8 | workflow_dispatch: 9 | 10 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 11 | jobs: 12 | # This workflow contains a single job called "build" 13 | build: 14 | # The type of runner that the job will run on 15 | runs-on: ubuntu-latest 16 | 17 | # Steps represent a sequence of tasks that will be executed as part of the job 18 | steps: 19 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 20 | - uses: actions/checkout@v2 21 | 22 | - name: Set up Go 23 | uses: actions/setup-go@v2 24 | with: 25 | go-version: 1.17 26 | - name: Set up Ngrok 27 | run: | 28 | wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.tgz 29 | tar -zvxf ngrok-stable-linux-amd64.tgz -C . 30 | ./ngrok authtoken ${{ secrets.TOKEN }} 31 | - name: Install libs 32 | run: go mod tidy 33 | - name: Build 34 | run: go build 35 | - name: Run 36 | run: | 37 | chmod +x FileServer 38 | export PORT=8080 39 | screen -dmS ngrokscreen 40 | screen -S ngrokscreen -X stuff './ngrok http 8080\n' 41 | ./FileServer 42 | -------------------------------------------------------------------------------- /modules/api.go: -------------------------------------------------------------------------------- 1 | package modules 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "net/http" 8 | "os" 9 | "strings" 10 | 11 | "github.com/labstack/echo/v4" 12 | ) 13 | 14 | var FileIds = make(map[string]string) 15 | 16 | func DownloadFile(c echo.Context) error { 17 | link := c.Request().URL.Path 18 | 19 | if strings.Contains(link, "dl/name") { 20 | fileId := c.Param("name") 21 | filePath := fmt.Sprintf("downloads/%s", fileId) 22 | if _, err := os.Stat(filePath); os.IsNotExist(err) { 23 | return c.String(http.StatusNotFound, "File not found") 24 | } 25 | return c.Attachment(filePath, fileId) 26 | } 27 | 28 | fileId := c.Param("id") 29 | for id, name := range FileIds { 30 | if fileId == id { 31 | filePath := fmt.Sprintf("downloads/%s", name) 32 | return c.Attachment(filePath, name) 33 | } 34 | } 35 | return c.String(http.StatusNotFound, "File not found") 36 | } 37 | 38 | func HandleUpload(c echo.Context) error { 39 | // Source 40 | file, err := c.FormFile("file") 41 | log.Println("Upload:", file.Filename) 42 | if err != nil { 43 | return err 44 | } 45 | src, err := file.Open() 46 | if err != nil { 47 | return err 48 | } 49 | defer src.Close() 50 | 51 | // Destination 52 | dst, err := os.Create("downloads/" + file.Filename) 53 | if err != nil { 54 | return err 55 | } 56 | defer dst.Close() 57 | 58 | // Copy 59 | if _, err = io.Copy(dst, src); err != nil { 60 | return err 61 | } 62 | downloadId := RandomString(6) 63 | urlPath := "http://" + c.Request().Host + "/dl" 64 | shortLink := urlPath + "/id/" + downloadId 65 | longLink := urlPath + "/name/" + file.Filename 66 | FileIds[downloadId] = file.Filename 67 | 68 | return c.JSON(http.StatusOK, map[string]string{"fileName": file.Filename, "shortLink": shortLink, "longLink": longLink}) 69 | } 70 | -------------------------------------------------------------------------------- /html/upload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Upload Files 7 | 8 |

You can upload files from here!

9 |
10 |
11 | 12 |

13 |

14 |
15 | 61 | 62 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= 5 | github.com/labstack/echo/v4 v4.6.3 h1:VhPuIZYxsbPmo4m9KAkMU/el2442eB7EBFFhNTTT9ac= 6 | github.com/labstack/echo/v4 v4.6.3/go.mod h1:Hk5OiHj0kDqmFq7aHe7eDqI7CUhuCrfpupQtLGGLm7A= 7 | github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= 8 | github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= 9 | github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 10 | github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= 11 | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 12 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 13 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 14 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 15 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 16 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 17 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 18 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 19 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 20 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 21 | github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= 22 | github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 23 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 24 | golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 h1:kACShD3qhmr/3rLmg1yXyt+N4HcwutKyPRB93s54TIU= 25 | golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 26 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 27 | golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 28 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 29 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= 30 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 31 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 32 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 33 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 34 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 35 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 36 | golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 37 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= 39 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 40 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 41 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 42 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 43 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 44 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 45 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 46 | golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 47 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 48 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 49 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 50 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 51 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 52 | --------------------------------------------------------------------------------