Python Flask File CheckSum
Tags: python, webdev, beginners, programming
Published: 2022-08-20 20:16:39

Hello.! I hope you are doing great. Today we will learn how to make a small applictaion which will create checksum of file and evaluate the file with the checksum.

For the checksum I'll be using <code>SHA256</code> you can use whatever hasing algo you want. You can find the code in this [GitHub Repo](https://github.com/MuhammadSaim/flask-file-checksum).

Let's get started with the applictaion.

Make a new diretcory and step into it

```shell
mkdir flask-checksum && cd flask-checksum
```

Initialize the virtualenvironment 

```shell
python -m venv vnev
```

OR

```shell
virtualenv venv
```

Activate the virtualenv

```shell
source venv/bin/activate
```

Now it time to install flask

```shell
pip install flask
```

Now its time to create the diretcory structure for our applictaion I'll make it simple.

```
📦flask-checksum
 ┣ 📂static
 ┃ ┣ 📂css
 ┃ ┣ 📂js
 ┃ ┗ 📂uploads
 ┣ 📂templates
 ┃ ┣ 📂includes
 ┃ ┣ 📂layouts
 ┃ ┗ 📂pages
 ┗ 📜app.py
```

Download and place [CSS](https://bootswatch.com/5/lux/bootstrap.min.css) and [Js](https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js) files for this project in <code>static/css</code> and <code>static/js</code> respectively. After that your directory structure will look like this.

```
📦static
 ┣ 📂css
 ┃ ┗ 📜bootstrap.min.css
 ┣ 📂js
 ┃ ┗ 📜bootstrap.bundle.min.js
 ┗ 📂uploads
 ┃ ┗ 📜.gitignore
```

Now open <code>app.py</code> start building our applictaion and these line of code this will show output of the hello, world in your browser.

```python
from flask import Flask


app = Flask(__name__)

@app.route('/')
def index():
   return "Hello, World"


if __name__ == '__main__':
   app.run()
```

Run this application.


```shell
python app.py
```

This will start a server and you can access the application on this URL [127.0.0.1:5000](http://127.0.0.1:5000).

Its time to create templates for our applictaion in <code>templates/layouts</code> create <code>app.html</code> file this will be our master layout of the applictaion all these templates will extend this template.

**app.html**
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
</head>
<body class="bg-white-500">

    {% include 'includes/navbar.html' %}

    <div class="container">
        {% block content %}{% endblock %}
    </div>

    <script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
</body>
</html>
```

Create a file <code>navbar.html</code> in <code>templates/includes</code>.

**navbar.html**
```html
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
  <div class="container">
    <a class="navbar-brand" href="{{ url_for('create_checksum') }}">File CheckSum</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <a class="nav-link {% if request.endpoint == 'create_checksum' %} active {% endif %}" aria-current="page" href="{{ url_for('create_checksum') }}">Create</a>
        </li>
        <li class="nav-item">
          <a class="nav-link {% if request.endpoint == 'verify_checksum' %} active {% endif %}" href="{{ url_for('verify_checksum') }}">Verify</a>
        </li>
      </ul>
    </div>
  </div>
</nav>
```

Now we need two more templates for our applictaion one for creating checksum and 2nd for verifing. Let's create two more files in <code>templates/pages</code> first will be <code>create.html</code> and 2nd will be <code>verify.html</code>.

**create.html**
```html
{% extends 'layouts/app.html' %}

{% block title %} Create CheckSum {% endblock %}

{% block content %}

    <div class="row py-5">
        <div class="col-md-8 offset-md-2 col-sm-12">
            <div class="card shadow">
                <div class="card-body">
                    <h5 class="card-title">
                        Create CheckSum
                    </h5>
                    <form action="{{ url_for('create_checksum') }}" method="post" enctype="multipart/form-data">
                        <div class="mb-3">
                            <label for="formFile" class="form-label">File</label>
                            <input class="form-control" type="file" id="formFile" name="file">
                        </div>
                        <div class="mb-3 float-end">
                            <button class="btn btn-primary" type="submit">create</button>
                        </div>
                    </form>
                </div>
            </div>
            {% if checksum %}
            <div class="card shadow mt-3">
                <div class="card-body">
                    <h4 class="card-title">your CheckSum</h4>
                    <p class="bg-primary p-3 text-white">{{ checksum }}</p>
                </div>
            </div>
            {% endif %}
        </div>
    </div>

{% endblock %}
```

**verify.html**
```html
{% extends 'layouts/app.html' %}

{% block title %} Verify CheckSum {% endblock %}

{% block content %}

    <div class="row py-5">
        <div class="col-md-8 offset-md-2 col-sm-12">
            <div class="card shadow">
                <div class="card-body">
                    <h5 class="card-title">
                        Verify CheckSum
                    </h5>
                    <form action="{{ url_for('verify_checksum') }}" method="post" enctype="multipart/form-data">
                        <div class="mb-3">
                            <label for="formFile" class="form-label">File</label>
                            <input class="form-control" type="file" id="formFile" name="file">
                        </div>
                        <div class="mb-3">
                            <label for="checksum">CheckSum</label>
                            <input type="text" name="checksum" class="form-control" placeholder="CheckSum">
                        </div>
                        <div class="mb-3 float-end">
                            <button class="btn btn-primary" type="submit">Verify</button>
                        </div>
                    </form>
                </div>
            </div>
            {% if status != None %}
            <div class="card shadow mt-3">
                <div class="card-body">
                    {% if status %}
                        <div class="alert alert-success">Your file is authentic.</div>
                    {% else %}
                        <div class="alert alert-danger">Your file is not authentic.</div>
                    {% endif %}
                </div>
            </div>
            {% endif %}
        </div>
    </div>

{% endblock %}
```

So after that your <code>templates</code> directory structure will look like this.

```
📦templates
 ┣ 📂includes
 ┃ ┗ 📜navbar.html
 ┣ 📂layouts
 ┃ ┗ 📜app.html
 ┗ 📂pages
 ┃ ┣ 📜create.html
 ┃ ┗ 📜verify.html
```

Now create the main logic of our applictaion so we start with the creating checksum in <code>app.py</code> and this function in the file.

```python
@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)
```

After adding this function your <code>app.py</code> will look like this.

```python
from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import hashlib
import os


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)



if __name__ == '__main__':
    app.run(debug=True)
```

Now create our 2nd function for verifying the checksum.


```python
@app.route('/verify-checksum', methods=['GET', 'POST'])
def verify_checksum():
    status = None
    if request.method == 'POST':
        file = request.files['file']
        checksum = request.form.get('checksum')
        new_name = secure_filename(file.filename)
        file.save('static/uploads/' + new_name)
        new_checksum = sha256(new_name)
        status = checksum == new_checksum
        os.remove('static/uploads/' + new_name)
    return render_template('pages/verify.html', status=status)
```

After adding this function your <code>app.py</code> will look like this.

```python
from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import hashlib
import os


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)


@app.route('/verify-checksum', methods=['GET', 'POST'])
def verify_checksum():
    status = None
    if request.method == 'POST':
        file = request.files['file']
        checksum = request.form.get('checksum')
        new_name = secure_filename(file.filename)
        file.save('static/uploads/' + new_name)
        new_checksum = sha256(new_name)
        status = checksum == new_checksum
        os.remove('static/uploads/' + new_name)
    return render_template('pages/verify.html', status=status)


if __name__ == '__main__':
    app.run(debug=True)
```


Now its time for the main and important function of the application which will be the responsible for the hasing.

```python
def sha256(file_name):
    hash_sha256 = hashlib.sha256()
    with open('static/uploads/'+file_name, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_sha256.update(chunk)
    return hash_sha256.hexdigest()
```

After adding this function your <code>app.py</code> will look like this.

```python
from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import hashlib
import os


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def create_checksum():
    checksum = None
    if request.method == 'POST':
        file = request.files['file']
        new_name = secure_filename(file.filename)
        file.save('static/uploads/'+new_name)
        checksum = sha256(new_name)
        os.remove('static/uploads/'+new_name)
    return render_template('pages/create.html', checksum=checksum)


@app.route('/verify-checksum', methods=['GET', 'POST'])
def verify_checksum():
    status = None
    if request.method == 'POST':
        file = request.files['file']
        checksum = request.form.get('checksum')
        new_name = secure_filename(file.filename)
        file.save('static/uploads/' + new_name)
        new_checksum = sha256(new_name)
        status = checksum == new_checksum
        os.remove('static/uploads/' + new_name)
    return render_template('pages/verify.html', status=status)


def sha256(file_name):
    hash_sha256 = hashlib.sha256()
    with open('static/uploads/'+file_name, "rb") as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_sha256.update(chunk)
    return hash_sha256.hexdigest()


if __name__ == '__main__':
    app.run(debug=True)
```

Now its time to run the application

```shell
python app.py
```

```shell
http://127.0.0.1:5000
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ooef346k0rnxqf8iutp.gif)


Thanks for being with me.

If you want to learn Flask I have started my series [Flask For Beginners](https://dev.to/muhammadsaim/python-flask-series-for-beginners-3eli) Please do check out.

What you guys think and query and suggestion you have to feel free to write it down.

Thanks 🤗