From bef28cb377e8997979e9bec4d286c791e812125f Mon Sep 17 00:00:00 2001
From: Santosh Chejarla <santosh8@illinois.edu>
Date: Mon, 8 May 2023 02:21:42 +0100
Subject: [PATCH] updating code

---
 .gitignore                 |   0
 access_data.json           |   1 +
 app.py                     |  57 +++++-
 cache_validator.sh         |   2 +-
 constants.py               |   0
 index.html                 | 358 -------------------------------------
 lfu_checker.py             |   3 +-
 pi_logo.png                | Bin
 save_mode.json             |   1 +
 static/images/pi_logo.png  | Bin
 static/styles/styles.css   |  15 ++
 templates/delete.html      |  26 +++
 templates/index.html       |  21 ++-
 templates/login.html       |   2 +-
 templates/more_files.html  |  10 +-
 templates/upload.html      |   6 +-
 templates/upload_fail.html |   9 -
 upload.py                  |   0
 utils.py                   |  11 +-
 19 files changed, 134 insertions(+), 388 deletions(-)
 mode change 100644 => 100755 .gitignore
 mode change 100644 => 100755 access_data.json
 mode change 100644 => 100755 app.py
 mode change 100644 => 100755 constants.py
 delete mode 100755 index.html
 mode change 100644 => 100755 lfu_checker.py
 mode change 100644 => 100755 pi_logo.png
 mode change 100644 => 100755 save_mode.json
 mode change 100644 => 100755 static/images/pi_logo.png
 mode change 100644 => 100755 static/styles/styles.css
 create mode 100644 templates/delete.html
 mode change 100644 => 100755 templates/index.html
 mode change 100644 => 100755 templates/login.html
 mode change 100644 => 100755 templates/more_files.html
 mode change 100644 => 100755 templates/upload.html
 delete mode 100644 templates/upload_fail.html
 delete mode 100644 upload.py
 mode change 100644 => 100755 utils.py

diff --git a/.gitignore b/.gitignore
old mode 100644
new mode 100755
diff --git a/access_data.json b/access_data.json
old mode 100644
new mode 100755
index e69de29..9e26dfe
--- a/access_data.json
+++ b/access_data.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/app.py b/app.py
old mode 100644
new mode 100755
index d19fb8c..91b126c
--- a/app.py
+++ b/app.py
@@ -1,4 +1,4 @@
-from flask import Flask, render_template, request, redirect, url_for, flash, session, send_file, abort
+from flask import Flask, render_template, request, redirect, url_for, flash, session, send_file, abort, send_from_directory
 import os
 import boto3
 import json
@@ -27,6 +27,10 @@ def download_file(filename):
     except FileNotFoundError:
         abort(404)
 
+@app.route('/thumb/<path:filename>')
+def serve_thumb(filename):
+    return send_from_directory('./thumb', filename)
+
 
 # check if user is logged in else redirect to login page
 def check_login():
@@ -94,7 +98,6 @@ def upload():
                     if tot_size + file_size <= CACHE_SIZE:
                         break
             file.save(os.path.join(directory, filename))
-            return redirect(url_for('index'))
         elif location == "s3":
             with open("creds.json", "r") as f:
                 creds = json.load(f)
@@ -110,18 +113,23 @@ def upload():
                 lfu_obj = LFUChecker(CACHE_SIZE)
                 lfu_files = lfu_obj.get_lfu()
                 for _file in lfu_files:
+                    if lfu_files[_file] > 0: continue
                     if _file == filename: continue
                     if _file in files_with_auto_mode:
                         os.remove(os.path.join(os.getcwd(), 'cache', _file))
                     tot_size = get_total_files_size()
                     if tot_size + file_size <= CACHE_SIZE:
                         break
-            file.save(file_path)
-            file.seek(0)
+            tot_size = get_total_files_size()
+            if tot_size + file_size <= CACHE_SIZE:
+                file.save(file_path)
+                file.seek(0)
             with open("creds.json", "r") as f:
                 creds = json.load(f)
             s3 = boto3.client('s3',aws_access_key_id=creds["access_key"], aws_secret_access_key=creds["secret"])
-            s3.upload_fileobj(file, "hnas", filename)     
+            s3.upload_fileobj(file, "hnas", filename)
+        if "jpeg" in filename or "jpg" in filename or "png" in filename or "JPG" in filename:
+            generate_thumb(filename)   
         return redirect(url_for('index'))
 
     return render_template('upload.html')
@@ -169,13 +177,46 @@ def logout():
 def upload_fail():
     return render_template('upload_fail.html')
 
-@app.route('/delete/<path:filename>', methods=['GET'])
-def delete_file(filename):
+
+@app.route('/delete_page')
+def delete_page():
     if not check_login():
         return redirect(url_for('login'))
-    os.remove(os.path.join(os.getcwd(), 'cache', filename))
+    files = set(get_local_files() + get_s3_files())
+    return render_template('delete.html', files=files)
+
+@app.route('/delete', methods=['POST'])
+def delete_file():
+    if not check_login():
+        return redirect(url_for('login'))
+
+    filename = request.form.get('delete-file')
+    if filename:
+        local_file_path = os.path.join(os.getcwd(), 'cache', filename)
+        s3_file_path = filename
+        if os.path.exists(local_file_path):
+            os.remove(local_file_path)
+        else:
+            with open("creds.json", "r") as f:
+                creds = json.load(f)
+            s3 = boto3.client('s3', aws_access_key_id=creds["access_key"], aws_secret_access_key=creds["secret"])
+            s3.delete_object(Bucket="hnas", Key=s3_file_path)
+        with open("access_data.json", "r+") as f:
+            access_data = json.load(f)
+            access_data.pop(filename, None)
+            f.seek(0)
+            json.dump(access_data, f)
+            f.truncate()
+        with open("save_mode.json", "r+") as f:
+            save_mode_data = json.load(f)
+            save_mode_data.pop(filename, None)
+            f.seek(0)
+            json.dump(save_mode_data, f)
+            f.truncate()
+
     return redirect(url_for('index'))
 
+
 # index page
 @app.route('/')
 def index():
diff --git a/cache_validator.sh b/cache_validator.sh
index 92aa48e..0078e47 100755
--- a/cache_validator.sh
+++ b/cache_validator.sh
@@ -1,2 +1,2 @@
-cd /var/www/html
+cd /home/pi/iot_project
 python3 lfu_checker.py
\ No newline at end of file
diff --git a/constants.py b/constants.py
old mode 100644
new mode 100755
diff --git a/index.html b/index.html
deleted file mode 100755
index 20b6d62..0000000
--- a/index.html
+++ /dev/null
@@ -1,358 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-    <title>Apache2 Ubuntu Default Page: It works</title>
-    <style type="text/css" media="screen">
-  * {
-    margin: 0px 0px 0px 0px;
-    padding: 0px 0px 0px 0px;
-  }
-
-  body, html {
-    padding: 3px 3px 3px 3px;
-
-    background-color: #D8DBE2;
-
-    font-family: Ubuntu, Verdana, sans-serif;
-    font-size: 11pt;
-    text-align: center;
-  }
-
-  div.main_page {
-    position: relative;
-    display: table;
-
-    width: 800px;
-
-    margin-bottom: 3px;
-    margin-left: auto;
-    margin-right: auto;
-    padding: 0px 0px 0px 0px;
-
-    border-width: 2px;
-    border-color: #212738;
-    border-style: solid;
-
-    background-color: #FFFFFF;
-
-    text-align: center;
-  }
-
-  div.page_header {
-    height: 180px;
-    width: 100%;
-
-    background-color: #F5F6F7;
-  }
-
-  div.page_header span {
-    margin: 15px 0px 0px 50px;
-
-    font-size: 180%;
-    font-weight: bold;
-  }
-
-  div.page_header img {
-    margin: 3px 0px 0px 40px;
-
-    border: 0px 0px 0px;
-  }
-
-  div.banner {
-    padding: 9px 6px 9px 6px;
-    background-color: #E9510E;
-    color: #FFFFFF;
-    font-weight: bold;
-    font-size: 112%;
-    text-align: center;
-    position: absolute;
-    left: 40%;
-    bottom: 30px;
-    width: 20%;
-  }
-
-  div.table_of_contents {
-    clear: left;
-
-    min-width: 200px;
-
-    margin: 3px 3px 3px 3px;
-
-    background-color: #FFFFFF;
-
-    text-align: left;
-  }
-
-  div.table_of_contents_item {
-    clear: left;
-
-    width: 100%;
-
-    margin: 4px 0px 0px 0px;
-
-    background-color: #FFFFFF;
-
-    color: #000000;
-    text-align: left;
-  }
-
-  div.table_of_contents_item a {
-    margin: 6px 0px 0px 6px;
-  }
-
-  div.content_section {
-    margin: 3px 3px 3px 3px;
-
-    background-color: #FFFFFF;
-
-    text-align: left;
-  }
-
-  div.content_section_text {
-    padding: 4px 8px 4px 8px;
-
-    color: #000000;
-    font-size: 100%;
-  }
-
-  div.content_section_text pre {
-    margin: 8px 0px 8px 0px;
-    padding: 8px 8px 8px 8px;
-
-    border-width: 1px;
-    border-style: dotted;
-    border-color: #000000;
-
-    background-color: #F5F6F7;
-
-    font-style: italic;
-  }
-
-  div.content_section_text p {
-    margin-bottom: 6px;
-  }
-
-  div.content_section_text ul, div.content_section_text li {
-    padding: 4px 8px 4px 16px;
-  }
-
-  div.section_header {
-    padding: 3px 6px 3px 6px;
-
-    background-color: #8E9CB2;
-
-    color: #FFFFFF;
-    font-weight: bold;
-    font-size: 112%;
-    text-align: center;
-  }
-
-  div.section_header_grey {
-    background-color: #9F9386;
-  }
-
-  .floating_element {
-    position: relative;
-    float: left;
-  }
-
-  div.table_of_contents_item a,
-  div.content_section_text a {
-    text-decoration: none;
-    font-weight: bold;
-  }
-
-  div.table_of_contents_item a:link,
-  div.table_of_contents_item a:visited,
-  div.table_of_contents_item a:active {
-    color: #000000;
-  }
-
-  div.table_of_contents_item a:hover {
-    background-color: #000000;
-
-    color: #FFFFFF;
-  }
-
-  div.content_section_text a:link,
-  div.content_section_text a:visited,
-   div.content_section_text a:active {
-    background-color: #DCDFE6;
-
-    color: #000000;
-  }
-
-  div.content_section_text a:hover {
-    background-color: #000000;
-
-    color: #DCDFE6;
-  }
-
-  div.validator {
-  }
-    </style>
-  </head>
-  <body>
-    <div class="main_page">
-      <div class="page_header floating_element">
-        <img src="icons/ubuntu-logo.png" alt="Ubuntu Logo"
-             style="width:184px;height:146px;" class="floating_element" />
-        <div>
-          <span style="margin-top: 1.5em;" class="floating_element">
-            Apache2 Default Page
-          </span>
-        </div>
-        <div class="banner">
-          <div id="about"></div>
-          It works!
-        </div>
-
-      </div>
-      <div class="content_section floating_element">
-        <div class="content_section_text">
-          <p>
-                This is the default welcome page used to test the correct 
-                operation of the Apache2 server after installation on Ubuntu systems.
-                It is based on the equivalent page on Debian, from which the Ubuntu Apache
-                packaging is derived.
-                If you can read this page, it means that the Apache HTTP server installed at
-                this site is working properly. You should <b>replace this file</b> (located at
-                <tt>/var/www/html/index.html</tt>) before continuing to operate your HTTP server.
-          </p>
-
-          <p>
-                If you are a normal user of this web site and don't know what this page is
-                about, this probably means that the site is currently unavailable due to
-                maintenance.
-                If the problem persists, please contact the site's administrator.
-          </p>
-
-        </div>
-        <div class="section_header">
-          <div id="changes"></div>
-                Configuration Overview
-        </div>
-        <div class="content_section_text">
-          <p>
-                Ubuntu's Apache2 default configuration is different from the
-                upstream default configuration, and split into several files optimized for
-                interaction with Ubuntu tools. The configuration system is
-                <b>fully documented in
-                /usr/share/doc/apache2/README.Debian.gz</b>. Refer to this for the full
-                documentation. Documentation for the web server itself can be
-                found by accessing the <a href="/manual">manual</a> if the <tt>apache2-doc</tt>
-                package was installed on this server.
-          </p>
-          <p>
-                The configuration layout for an Apache2 web server installation on Ubuntu systems is as follows:
-          </p>
-          <pre>
-/etc/apache2/
-|-- apache2.conf
-|       `--  ports.conf
-|-- mods-enabled
-|       |-- *.load
-|       `-- *.conf
-|-- conf-enabled
-|       `-- *.conf
-|-- sites-enabled
-|       `-- *.conf
-          </pre>
-          <ul>
-                        <li>
-                           <tt>apache2.conf</tt> is the main configuration
-                           file. It puts the pieces together by including all remaining configuration
-                           files when starting up the web server.
-                        </li>
-
-                        <li>
-                           <tt>ports.conf</tt> is always included from the
-                           main configuration file. It is used to determine the listening ports for
-                           incoming connections, and this file can be customized anytime.
-                        </li>
-
-                        <li>
-                           Configuration files in the <tt>mods-enabled/</tt>,
-                           <tt>conf-enabled/</tt> and <tt>sites-enabled/</tt> directories contain
-                           particular configuration snippets which manage modules, global configuration
-                           fragments, or virtual host configurations, respectively.
-                        </li>
-
-                        <li>
-                           They are activated by symlinking available
-                           configuration files from their respective
-                           *-available/ counterparts. These should be managed
-                           by using our helpers
-                           <tt>
-                                a2enmod,
-                                a2dismod,
-                           </tt>
-                           <tt>
-                                a2ensite,
-                                a2dissite,
-                            </tt>
-                                and
-                           <tt>
-                                a2enconf,
-                                a2disconf
-                           </tt>. See their respective man pages for detailed information.
-                        </li>
-
-                        <li>
-                           The binary is called apache2 and is managed using systemd, so to
-                           start/stop the service use <tt>systemctl start apache2</tt> and
-                           <tt>systemctl stop apache2</tt>, and use <tt>systemctl status apache2</tt>
-                           and <tt>journalctl -u apache2</tt> to check status.  <tt>system</tt>
-                           and <tt>apache2ctl</tt> can also be used for service management if
-                           desired.
-                           <b>Calling <tt>/usr/bin/apache2</tt> directly will not work</b> with the
-                           default configuration.
-                        </li>
-          </ul>
-        </div>
-
-        <div class="section_header">
-            <div id="docroot"></div>
-                Document Roots
-        </div>
-
-        <div class="content_section_text">
-            <p>
-                By default, Ubuntu does not allow access through the web browser to
-                <em>any</em> file outside of those located in <tt>/var/www</tt>,
-                <a href="http://httpd.apache.org/docs/2.4/mod/mod_userdir.html" rel="nofollow">public_html</a>
-                directories (when enabled) and <tt>/usr/share</tt> (for web
-                applications). If your site is using a web document root
-                located elsewhere (such as in <tt>/srv</tt>) you may need to whitelist your
-                document root directory in <tt>/etc/apache2/apache2.conf</tt>.
-            </p>
-            <p>
-                The default Ubuntu document root is <tt>/var/www/html</tt>. You
-                can make your own virtual hosts under /var/www.
-            </p>
-        </div>
-
-        <div class="section_header">
-          <div id="bugs"></div>
-                Reporting Problems
-        </div>
-        <div class="content_section_text">
-          <p>
-                Please use the <tt>ubuntu-bug</tt> tool to report bugs in the
-                Apache2 package with Ubuntu. However, check <a
-                href="https://bugs.launchpad.net/ubuntu/+source/apache2"
-                rel="nofollow">existing bug reports</a> before reporting a new bug.
-          </p>
-          <p>
-                Please report bugs specific to modules (such as PHP and others)
-                to their respective packages, not to the web server itself.
-          </p>
-        </div>
-
-      </div>
-    </div>
-    <div class="validator">
-    </div>
-  </body>
-</html>
diff --git a/lfu_checker.py b/lfu_checker.py
old mode 100644
new mode 100755
index a0135d7..7af3e23
--- a/lfu_checker.py
+++ b/lfu_checker.py
@@ -54,7 +54,8 @@ class LFUChecker:
                 continue
             else:
                 if curr_size + get_file_size(file) > self.cache:
-                    os.remove(os.path.join(os.getcwd(), 'cache', file))
+                    if file in local_files:
+                        os.remove(os.path.join(os.getcwd(), 'cache', file))
                     fill = True
                 else:
                     curr_size += get_file_size(file)
diff --git a/pi_logo.png b/pi_logo.png
old mode 100644
new mode 100755
diff --git a/save_mode.json b/save_mode.json
old mode 100644
new mode 100755
index e69de29..9e26dfe
--- a/save_mode.json
+++ b/save_mode.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/static/images/pi_logo.png b/static/images/pi_logo.png
old mode 100644
new mode 100755
diff --git a/static/styles/styles.css b/static/styles/styles.css
old mode 100644
new mode 100755
index e21903f..5c2957b
--- a/static/styles/styles.css
+++ b/static/styles/styles.css
@@ -54,4 +54,19 @@ body {
 ul.dashed > li:before {
   content: "-";
   text-indent: -5px;
+}
+
+.file-container-img li {
+  content: none;
+}
+
+.delete-btn {
+  position: absolute;
+  bottom: -50%;
+  right: 2%;
+  background: #363636;
+  border-radius: 10px;
+  padding: 0.5vw;
+  color: #fff;
+  text-decoration: none;
 }
\ No newline at end of file
diff --git a/templates/delete.html b/templates/delete.html
new file mode 100644
index 0000000..b85e4a9
--- /dev/null
+++ b/templates/delete.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>File Delete</title>
+    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/styles.css') }}">
+</head>
+<body>
+    <div class="logo-container">
+        <a href="/">
+        <img src="{{ url_for('static', filename='images/pi_logo.png') }}" alt="logo" width="100" height="100">
+        </a>
+        <h1>File Delete</h1>
+    </div>
+    <div class="container" style="display: flex; justify-content: center; align-items: center;">
+        <form method="POST" action="{{ url_for('delete_file') }}">
+            <label for="delete-file">Delete file:</label>
+            <select name="delete-file" id="delete-file">
+                {% for file in files %}
+                <option value="{{ file }}">{{ file }}</option>
+                {% endfor %}
+            </select>
+            <button type="submit" class="btn btn-danger">Delete</button>
+        </form>
+    </div>
+</body>
+</html>
diff --git a/templates/index.html b/templates/index.html
old mode 100644
new mode 100755
index 3ed4165..1a31abf
--- a/templates/index.html
+++ b/templates/index.html
@@ -19,18 +19,23 @@
 			<h2><i class="icon-camera"> </i>Image Files</i></h2>
 			<hr>
 			{% if imgfiles %}
-				 <ul>
+			  <ul>
 				{% for file in imgfiles %}
-					<li><a href="{{ url_for('download_file', filename=file) }}">{{ file }}</a></li>
+				  <li>
+					<a href="{{ url_for('download_file', filename=file) }}">
+					  <img src="{{ url_for('serve_thumb', filename=file) }}"  width="100">
+					  <!-- {{ file }} -->
+					</a>
+				  </li>
 				{% endfor %}
-				</ul>
+			  </ul>
 			{% else %}
-				<p>No image files found.</p>
+			  <p>No image files found.</p>
 			{% endif %}
 			{% if mimages %}
-				<a href="/images">see more...</a>
+			  <a href="/images">see more...</a>
 			{% endif %}
-		</div>
+		  </div>		  
 		<div class="file-container">
 		<h2><i class="icon-facetime-video"></i> Video Files</h2><hr>
 			{% if videofiles %}
@@ -77,5 +82,9 @@
 			{% endif %}
 		</div>
 	</div>
+	<div class="container">
+		<a href="/delete_page" class="delete-btn">Delete</a>
+	  </div>
+	  
 </body>
 </html>
diff --git a/templates/login.html b/templates/login.html
old mode 100644
new mode 100755
index d5e2b11..fa3493f
--- a/templates/login.html
+++ b/templates/login.html
@@ -9,7 +9,7 @@
     <img src="{{ url_for('static',filename='images/pi_logo.png') }}" alt="logo" width="100" height="100">
     <h1>Welcome to H-NAS!</h1>
   </div>
-  <div class="container">
+  <div class="container" style="display: flex; justify-content: center; align-items: center;">
     <form method="POST" action="/login">
       <label for="username">Username:</label>
       <input type="text" id="username" name="username"><br><br>
diff --git a/templates/more_files.html b/templates/more_files.html
old mode 100644
new mode 100755
index 4be89d1..9448988
--- a/templates/more_files.html
+++ b/templates/more_files.html
@@ -14,11 +14,19 @@
 	</div>
 	<!--print all elements from parameter files passed from flask-->
 	<div class="container" style="height: 90vh;">
-		<div class="file-container">
+		<div class="file-container-img">
 			<h2><i class="{{ fa_content }}"></i> {{ content }} Files</h2>
 				 <ul>
 				{% for file in files %}
+				{% if content=="Image" %}
+				<li>
+					<a href="{{ url_for('download_file', filename=file) }}">
+						<img src="{{ url_for('serve_thumb', filename=file) }}"  width="100">
+					</a>
+				</li>
+				{% else %}
 					<li><a href="{{ url_for('download_file', filename=file) }}">{{ file }}</a></li>
+				{% endif %}
 				{% endfor %}
 				</ul>
 		</div>
diff --git a/templates/upload.html b/templates/upload.html
old mode 100644
new mode 100755
index 13cf4d7..831b204
--- a/templates/upload.html
+++ b/templates/upload.html
@@ -5,11 +5,13 @@
 	<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/styles.css') }}">
 </head>
 <body>
-	<div class="logo-container" style="height: 10vh;">
+	<div class="logo-container">
+		<a href="/">
 		<img src="{{ url_for('static', filename='images/pi_logo.png') }}" alt="logo" width="100" height="100">
+		</a>
 		<h1>File Upload</h1>
 	</div>
-	<div class="container" style="height: 90vh;">
+	<div class="container" style="display: flex; justify-content: center; align-items: center;">
 		<form method="POST" action="{{ url_for('upload') }}" enctype="multipart/form-data">
 			<label for="file">Select a file:</label>
 			<input type="file" name="file"><br><br>
diff --git a/templates/upload_fail.html b/templates/upload_fail.html
deleted file mode 100644
index 7be4b6e..0000000
--- a/templates/upload_fail.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<title>Dashboard</title>
-	<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='styles/styles.css') }}">
-</head>
-<body>
-    <h1>Upload failed</h1>
-</body>
\ No newline at end of file
diff --git a/upload.py b/upload.py
deleted file mode 100644
index e69de29..0000000
diff --git a/utils.py b/utils.py
old mode 100644
new mode 100755
index 6fff3ec..219078a
--- a/utils.py
+++ b/utils.py
@@ -1,6 +1,7 @@
 import boto3
 import json
 import os
+from PIL import Image
 
 def get_total_files_size():
     directory = os.path.join(os.getcwd(), 'cache')
@@ -26,7 +27,7 @@ def categorize_files(files):
     for file in files:
         if file.endswith(".pdf"):
             pdfs.append(file)
-        elif file.endswith(".jpg") or file.endswith(".png"):
+        elif file.endswith(".jpg") or file.endswith(".png") or file.endswith("JPG") or file.endswith("jpeg"):
             images.append(file)
         elif file.endswith(".mp4"):
             videos.append(file)
@@ -83,3 +84,11 @@ def get_file_with_auto_mode():
         if save_mode_data[key] == "auto":
             auto_files.append(key)
     return auto_files
+
+
+def generate_thumb(filename):
+    """generate thumbnail for image and save in /thubmnails folder"""
+    directory = os.path.join(os.getcwd(), 'cache')
+    im = Image.open(os.path.join(directory, filename))
+    im.thumbnail((128, 128))
+    im.save(os.path.join('thumb', filename))
\ No newline at end of file
-- 
GitLab