The motivation behind this project was that I needed a very simple way for me and my friends to securely put files on my server for the various projects we use it for and the insane gigabit download speeds. Previously we just used rsync, a Linux command line utility that uses ssh to transfer files to and from another machine. This has many problems, mainly the fact that you need ssh and rsync installed which is a pain to do on Windows and doing it from a mobile device is out of the question. Secondly you need to add your ssh public key to the target server, this has some security issues because they have an actual linux user to run arbitrary code and after the infamous meltdown exploit i'm not willing to take that risk.

Of course we could just go back to using Google Drive but the free storage space is limited. We could use one of the many basic PHP uploaders but no, let's do it my way.

Over the span of 2 days I threw together some server-side Dart and some front-end html/css based off of my home website to make a unique way of uploading files:

2018-05-13-03_31_38-Window

Basically how it works is, I generate a token which grants a certain amount of storage space and when you upload a file it uses up that token's storage space.
You can add multiple tokens and choose which ones to use first, the file list is based off what files use it and when you delete a file it will give you back the storage space the file took.

2018-05-13-03_39_28-Window

In the settings menu you can delete and re-order tokens, it will fill your storage space from the top down and supports sharing files between multiple tokens so that if you had two 100MB tokens you could upload a 200MB file.

2018-05-13-03_47_10-Window

Drag-dropping files works as a bonus!

Setting it up is really simple, the backend is written in Dart (as usual) and can either be used self-contained as it's own webserver or through another webserver that is better at serving static files and supports like what I did with NGINX.

NGINX config:

server {
    listen 80;
    server_name u.pxtst.com;
    location / {
        rewrite ^(.*)$ https://u.pxtst.com$1 permanent;
    }
}


server {
        listen 443;
        listen [::]:443;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_stapling on;
        ssl_stapling_verify on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        ssl on;
        server_name u.pxtst.com;
        ssl_certificate /etc/letsencrypt/live/u.pxtst.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/u.pxtst.com/privkey.pem;

        root /home/upload/;

        index index.html index.htm index.nginx-debian.html;

        location /api {
                proxy_pass http://localhost:17132;
                proxy_set_header    Host            $host;
                proxy_set_header    X-Real-IP       $remote_addr;
                proxy_set_header    X-Forwarded-for $remote_addr;
                port_in_redirect off;
                proxy_redirect   http://IP:17132/  /;
                proxy_connect_timeout 300;
                client_max_body_size 1G;
        }
        
        location /upload {
                alias /home/upload/www;
                index index.html;
                try_files $uri $uri/ =404;
        }
        
        location / {
                gzip            on;
                gzip_min_length 1000;
                gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
                expires 7d;
                alias /home/upload/uploads/;
                try_files $uri =403;
        }
}

Sauce: https://lab.pxtst.com/PixelToast/file-uploader