DEV Community

Rukchad Wongprayoon
Rukchad Wongprayoon

Posted on

Online Storage with Flask!

Do you want a online storage made by yourself for keeping stuff?

Well here we are! Online storage with our lovely flask!

How this work?

So this project was all about serving file with flask and learn how to do some http request stuff!

Requirements

  1. Flask
  2. Python 3.7

Work time!

So first we are going to spawn flask application and import some stuff!

from random import sample
from string import ascii_letters,digits
from base64 import b64decode
from json import load,dump
import flask

app = flask.Flask("Really Awesome Storage API!")
Enter fullscreen mode Exit fullscreen mode

And next we some cool logger for tracking users posting and get some files!

def write(ip:str,file:str):
    with open("list.json","r") as i:
        ips = load(i)
        if ip not in list(ips):
            ips[ip] = []
        ips[ip].append(file)
    with open("list.json","w") as i:
        dump(ips,i)
        return True
Enter fullscreen mode Exit fullscreen mode

So this function is take two args is Ip address of user and file!

Now let's write a url that gonna let us upload stuff!

@app.route('/save',methods=['POST'])
def save():
    image = b64decode(flask.request.data)
    string = ''.join(sample(ascii_letters+digits,10)) + flask.request.headers.get("extension")
    a = open("stuff/" + string,"wb")
    a.write(image)
    a.close()
    write(flask.request.remote_addr,f"POST {string}")
    return string ,202
Enter fullscreen mode Exit fullscreen mode

Now this function will work if you go to save uri so this will take file that was base 64 encoded in body of response and it gonna create a file and write a bytes after that we close the file and log the file after that we will return random string with extension of the file that storage in our server!

Now let's write a uri path that gonna send file back!

@app.route('/<pic>')
def get(pic):
    try:
        a = flask.send_file("stuff/" + pic,as_attachment=True if flask.request.args.get("preview") is not None or flask.request.args.get("preview") == "false" else False)
        write(flask.request.remote_addr,f"GET {pic} FILE ")
    except Exception as e:
        return str(e)
    else:
        return a
Enter fullscreen mode Exit fullscreen mode

This function is somehow longer than what you may expected to but we have try that flask gonna send file back to user because flask will throw error if file not exist and we do a logger and if flask raise error we will throw error back to page if else then return file!
(SEND FILE FUNCTION IS REALLY DISCOURAGED! PLEASE USE SEND_FROM_DIRECTORY BY DOING THIS!

@app.route('/<pic>')
def get(pic):
    try:
        a = flask.send_from_directory("stuff",pic)
        write(flask.request.remote_addr,f"GET {pic} FILE ")
    except Exception as e:
        return str(e)
    else:
        return a

Enter fullscreen mode Exit fullscreen mode

I USE THIS CAUSE IT HAVE as_attachment ARGUMENT!)

It's that easy! Now let's write client side script!

Everyone can do so I will give you this snippet

from requests import post
from base64 import b64encode
from PIL import ImageGrab
from sys import exit
from os import remove
from os.path import splitext
while True:
    choices = input("Screenshot (s) or File (f) or Clipboard Text(ct) or Text (t) or Quit (q)\n")
    if "s" in a or "S" in choices:
        screen = ImageGrab.grabclipboard()
        screen.save("pic.jpg")
        print("Your screenshot is at https://content.biomooping.tk/" + post("yourlink/save",data=b64encode(open("pic.jpg","rb").read()),headers={"extension":splitext("./pic.jpg")[1]}).text)
        remove("pic.jpg")
    elif "f" in a or "F" in choices:
        path = input("Your file path\n")
        print("Your file is at is at https://content.biomooping.tk/" + post("yourlink/save",data=b64encode(open(path,"rb").read()),headers={"extension":splitext(path)[1]}).text)
    elif choices.startswith("ct") or choices.startswith("CT"):
        from clipboard import paste
        print("Your file is at is at https://content.biomooping.tk/" + post("yourlink/save",data=b64encode(paste()),headers={"extension":"txt"}).text)
    elif choices.startswith("T") or choices.startswith("t"):
        print("Your file is at is at https://content.biomooping.tk/" + post("yourlink/save",data=b64encode(bytes(input("Text\n\a"),encoding="utf-8")),headers={"extension":"txt"}).text)
    elif "q" in a or "Q" in choices:
        exit("See you next time!")
    else:
        continue
Enter fullscreen mode Exit fullscreen mode

This have feature is

  1. Get Screenshot from clipboard
  2. File uploading
  3. Clipboard text (On windows work but other os? i don't know.....)
  4. Text

Little question

Q: Why base64 encoding?

A: It is easiest thing that I know

Q: What inspire you to make this?

A:I always forget what my homework is so I want memo and I want to playaround with flask also I want online storage hosted on internet.

Github Repository!

Discussion (4)

Collapse
michaelcurrin profile image
Michael • Edited

Thanks for sharing.

A tip. I see you use with for your JSON but should do it for an image too.

If there is an error inside the first bit, close will never run and this is bad for memory and having multiple writers/readers of a file.

a = open("stuff/" + string,"wb")
a.write(image)
a.close()
Enter fullscreen mode Exit fullscreen mode

The Pythonic way is to use a with context block. I used f_out for "file out", but f is also common. More typical than a generic a. And I renamed path (or could be filename because string is vague and doesn't tell us what the value means or is for.

with open(f"stuff/{path}", "wb") as f_out:
    f_out.write(image)
Enter fullscreen mode Exit fullscreen mode

No need to do .close() ! :)

Also keep some whitespace after your commas and add some empty lines in your code - it feels dense to read which could put off a newbie.

Collapse
dumbstuff profile image
Rukchad Wongprayoon Author

Yeah! Thanks for tip!

Collapse
michaelcurrin profile image
Michael

This have feature is

Maybe rather:

"This as the following features"

Collapse
michaelcurrin profile image
Michael

Some recommended links

Base64 cheatsheet

michaelcurrin.github.io/dev-cheats...

Flask page

pypi.org/project/Flask/