diff --git a/.gitignore b/.gitignore
index 811b412bf0f69fa5de11436b2848400a30913319..1443a8e2741d5ca43913df83ff5cc7e81e47ac9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,6 @@
 *.py[cod]
 *.egg-info/
 space_images/
-item_images/
\ No newline at end of file
+item_images/
+dist/
+build/
\ No newline at end of file
diff --git a/spotseeker_server/test/item/image_thumbnail.py b/spotseeker_server/test/item/image_thumbnail.py
index 6efde82391146a21263c970bf7f3c49ac957fff2..9ad76d68807ffaa24e41d7235203b065a591f80b 100644
--- a/spotseeker_server/test/item/image_thumbnail.py
+++ b/spotseeker_server/test/item/image_thumbnail.py
@@ -15,9 +15,9 @@ from django.conf import settings
 from django.core.files import File
 from django.test.client import Client
 from spotseeker_server.models import Item, ItemImage, Spot
-from io import StringIO
+from io import BytesIO
 from PIL import Image
-from os.path import abspath, dirname
+from os.path import abspath, dirname, join
 from django.test.utils import override_settings
 from mock import patch
 from django.core import cache
@@ -25,7 +25,6 @@ from spotseeker_server import models
 
 TEST_ROOT = abspath(dirname(__file__))
 
-
 @override_settings(SPOTSEEKER_AUTH_MODULE='spotseeker_server.auth.all_ok')
 @override_settings(SPOTSEEKER_AUTH_ADMINS=('demo_user',))
 class ItemImageThumbTest(TestCase):
@@ -51,10 +50,11 @@ class ItemImageThumbTest(TestCase):
         dummy_cache = cache.caches['dummy']
         with patch.object(models, 'cache', dummy_cache):
             c = Client()
-            f = open("%s/../resources/test_jpeg.jpg" % TEST_ROOT)
+            f = open("%s/test_jpeg.jpg" % settings.MEDIA_ROOT, 'rb')
+            img = BytesIO(f.read())
             response = c.post(
                 self.url,
-                {"description": "This is a jpeg", "image": f}
+                {"description": "This is a jpeg", "image": img}
             )
             f.close()
 
@@ -63,7 +63,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 100, 100)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -83,7 +83,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 1, 100)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -103,7 +103,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 100, 1)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -129,7 +129,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 1, 1)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -149,7 +149,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 200, 200)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -218,7 +218,7 @@ class ItemImageThumbTest(TestCase):
         dummy_cache = cache.caches['dummy']
         with patch.object(models, 'cache', dummy_cache):
             c = Client()
-            f = open("%s/../resources/test_png.png" % TEST_ROOT)
+            f = open("%s/test_png.png" % settings.MEDIA_ROOT, 'rb')
             response = c.post(
                 self.url,
                 {"description": "This is a png", "image": f}
@@ -230,7 +230,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 100, 100)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -250,7 +250,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 1, 100)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -270,7 +270,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 100, 1)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -290,7 +290,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 1, 1)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -309,7 +309,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 200, 200)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -372,7 +372,7 @@ class ItemImageThumbTest(TestCase):
         dummy_cache = cache.caches['dummy']
         with patch.object(models, 'cache', dummy_cache):
             c = Client()
-            f = open("%s/../resources/test_gif.gif" % TEST_ROOT)
+            f = open("%s/test_gif.gif" % settings.MEDIA_ROOT, 'rb')
             response = c.post(
                 self.url,
                 {"description": "This is a gif", "image": f}
@@ -384,7 +384,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 100, 100)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -404,7 +404,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 1, 100)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -422,7 +422,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 100, 1)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -438,7 +438,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 1, 1)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -460,7 +460,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/{1}x{2}".format(new_base_location, 200, 200)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -526,7 +526,7 @@ class ItemImageThumbTest(TestCase):
 
             item = Item.objects.create(name="This is to test getting images")
 
-            f = open("%s/../resources/test_gif.gif" % TEST_ROOT)
+            f = open("%s/test_gif.gif" % settings.MEDIA_ROOT, 'rb')
             gif = ItemImage.objects.create(
                 description="This is the GIF test",
                 item=item,
@@ -546,13 +546,14 @@ class ItemImageThumbTest(TestCase):
         dummy_cache = cache.caches['dummy']
         with patch.object(models, 'cache', dummy_cache):
             c = Client()
-            img_path = "%s/../resources/test_jpeg2.jpg" % TEST_ROOT
-            f = open(img_path)
+            img_path = "%s/test_jpeg2.jpg" % settings.MEDIA_ROOT
+            f = open(img_path, 'rb')
+            img = BytesIO(f.read())
             response = c.post(
                 self.url,
-                {"description": "This is a jpg", "image": f}
+                {"description": "This is a jpg", "image": img}
             )
-            orig_im = Image.open(img_path)
+            orig_im = Image.open(img)
             f.close()
 
             new_base_location = response["Location"]
@@ -561,7 +562,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/constrain/width:{1}".format(new_base_location, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -586,7 +587,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/hei"
                 "ght:{1}".format(new_base_location, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -613,7 +614,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/width:{1},hei"
                 "ght:{2}".format(new_base_location, 75, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -636,7 +637,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/height:{1},wid"
                 "th:{2}".format(new_base_location, 75, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -646,7 +647,8 @@ class ItemImageThumbTest(TestCase):
             self.assertEqual(im.size[1], 75,
                               "Height on same size jpg thumbnail is 50")
             orig_ratio = orig_im.size[1] / orig_im.size[0]
-            ratio = im.size[1] / im.size[0]
+            # Use integer division (i.e. floor) because 75 is odd
+            ratio = im.size[1] // im.size[0]
             self.assertEqual(ratio, orig_ratio,
                               "Ratio on constrained jpg thumbnail is the same")
             self.assertEqual(
@@ -659,8 +661,8 @@ class ItemImageThumbTest(TestCase):
         dummy_cache = cache.caches['dummy']
         with patch.object(models, 'cache', dummy_cache):
             c = Client()
-            img_path = "%s/../resources/test_png2.png" % TEST_ROOT
-            f = open(img_path)
+            img_path = "%s/test_png2.png" % settings.MEDIA_ROOT
+            f = open(img_path, 'rb')
             response = c.post(self.url,
                               {"description": "This is a png", "image": f})
             orig_im = Image.open(img_path)
@@ -672,7 +674,7 @@ class ItemImageThumbTest(TestCase):
             response = c.get(
                 "{0}/thumb/constrain/width:{1}".format(new_base_location, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -696,7 +698,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/hei"
                 "ght:{1}".format(new_base_location, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -720,7 +722,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/width:{1},hei"
                 "ght:{2}".format(new_base_location, 75, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(response["Content-type"], "image/png",
                               "Content type of same size thumbnail is png")
@@ -741,7 +743,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/height:{1},wid"
                 "th:{2}".format(new_base_location, 75, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -751,7 +753,8 @@ class ItemImageThumbTest(TestCase):
             self.assertEqual(im.size[1], 75,
                               "Height on same size png thumbnail is 50")
             orig_ratio = orig_im.size[1] / orig_im.size[0]
-            ratio = im.size[1] / im.size[0]
+            # Use integer division (i.e. floor) because 75 is odd
+            ratio = im.size[1] // im.size[0]
             self.assertEqual(
                 ratio,
                 orig_ratio,
@@ -767,8 +770,8 @@ class ItemImageThumbTest(TestCase):
         dummy_cache = cache.caches['dummy']
         with patch.object(models, 'cache', dummy_cache):
             c = Client()
-            img_path = "%s/../resources/test_gif2.gif" % TEST_ROOT
-            f = open(img_path)
+            img_path = "%s/test_gif2.gif" % settings.MEDIA_ROOT
+            f = open(img_path, 'rb')
             response = c.post(
                 self.url,
                 {"description": "This is a gif", "image": f}
@@ -783,7 +786,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/wid"
                 "th:{1}".format(new_base_location, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -810,7 +813,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/hei"
                 "ght:{1}".format(new_base_location, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -837,7 +840,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/width:{1},hei"
                 "ght:{2}".format(new_base_location, 75, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -861,7 +864,7 @@ class ItemImageThumbTest(TestCase):
                 "{0}/thumb/constrain/height:{1},wid"
                 "th:{2}".format(new_base_location, 75, 50)
             )
-            data = StringIO(response.content)
+            data = BytesIO(response.content)
             im = Image.open(data)
             self.assertEqual(
                 response["Content-type"],
@@ -871,7 +874,8 @@ class ItemImageThumbTest(TestCase):
             self.assertEqual(im.size[1], 75,
                               "Height on same size gif thumbnail is 50")
             orig_ratio = orig_im.size[1] / orig_im.size[0]
-            ratio = im.size[1] / im.size[0]
+            # Use integer division (i.e. floor) because 75 is odd
+            ratio = im.size[1] // im.size[0]
             self.assertEqual(
                 ratio,
                 orig_ratio,
diff --git a/spotseeker_server/views/item_thumbnail.py b/spotseeker_server/views/item_thumbnail.py
index 50d808a0f557b274017e8aab09756182e660ff8b..9bca282d90972a903b3d1288fff3ef22258af3a1 100644
--- a/spotseeker_server/views/item_thumbnail.py
+++ b/spotseeker_server/views/item_thumbnail.py
@@ -25,7 +25,7 @@ from spotseeker_server.models import ItemImage, Item
 from django.http import HttpResponse
 from django.utils.http import http_date
 from spotseeker_server.require_auth import app_auth_required
-from io import StringIO
+from io import BytesIO
 from PIL import Image
 import time
 import re
@@ -90,7 +90,7 @@ class ItemThumbnailView(RESTDispatch):
         else:
             thumb = im.resize((thumb_width, thumb_height), Image.ANTIALIAS)
 
-        tmp = StringIO()
+        tmp = BytesIO()
         thumb.save(tmp, im.format, quality=95)
         tmp.seek(0)