forked from Gardener/ShareX_Storage
[WIP] adding thumbnails
This commit is contained in:
parent
d55e036ca1
commit
1fdc1d6ca9
11
README.md
11
README.md
@ -1,2 +1,13 @@
|
|||||||
# ShareX_Storage
|
# ShareX_Storage
|
||||||
Simple tool to act as endpoint to upload files through ShareX to.
|
Simple tool to act as endpoint to upload files through ShareX to.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
* [PyYAML](https://pypi.org/project/PyYAML/)
|
||||||
|
* [pycryptodomex](https://pypi.org/project/pycryptodomex/)
|
||||||
|
* [aiohttp](https://pypi.org/project/aiohttp/)
|
||||||
|
|
||||||
|
+ [thumbnail](https://pypi.org/project/thumbnail/) (optional)
|
||||||
|
+ [unoconv](https://github.com/unoconv/unoconv) (optional)
|
||||||
|
+ [ffmpeg](https://www.ffmpeg.org/) (optional)
|
||||||
|
+ [imagemagick](https://imagemagick.org/index.php) (optional)
|
||||||
|
+ [curl](https://curl.se/) (optional)
|
||||||
|
15
config.yaml
15
config.yaml
@ -27,3 +27,18 @@ base_url: 'https://your-domain.net/f/'
|
|||||||
# Should file extensions be appended to the generated links.
|
# Should file extensions be appended to the generated links.
|
||||||
# Links always work with or without file extensions (like puush.me).
|
# Links always work with or without file extensions (like puush.me).
|
||||||
show_ext: True
|
show_ext: True
|
||||||
|
|
||||||
|
# Should a frontend to view and manage uploads be exposed?
|
||||||
|
frontend: True
|
||||||
|
|
||||||
|
# Should thumbnails of uploaded files be created for frontend viewing.
|
||||||
|
thumbnails: True
|
||||||
|
|
||||||
|
# Directory for storing thumbnails
|
||||||
|
thumbnail_path: 'data/thumbs'
|
||||||
|
|
||||||
|
# Strategy for creating thumbnails. Possible values are:
|
||||||
|
# on-upload: Creates a thumbnail when uploading a file.
|
||||||
|
# on-request: Creates a thumbnail when requested by the frontend.
|
||||||
|
# both: Creates a thumbnail on request if one hasn't been created on upload.
|
||||||
|
thumbnail_strategy: 'both'
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
PyYAML
|
PyYAML
|
||||||
pycryptodomex
|
pycryptodomex
|
||||||
aiohttp
|
aiohttp
|
||||||
|
thumbnail
|
||||||
|
@ -10,6 +10,16 @@ from Cryptodome.Cipher import AES
|
|||||||
from Cryptodome.Util import Padding
|
from Cryptodome.Util import Padding
|
||||||
from aiohttp import web, hdrs
|
from aiohttp import web, hdrs
|
||||||
|
|
||||||
|
from thumbnail import generate_thumbnail
|
||||||
|
|
||||||
|
ThumbnailOptions = {
|
||||||
|
'trim': False,
|
||||||
|
'height': 300,
|
||||||
|
'width': 300,
|
||||||
|
'quality': 85,
|
||||||
|
'type': 'thumbnail'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class AppConfig:
|
class AppConfig:
|
||||||
_instance = None
|
_instance = None
|
||||||
@ -36,6 +46,10 @@ class AppConfig:
|
|||||||
self.show_ext = data.get('show_ext', True)
|
self.show_ext = data.get('show_ext', True)
|
||||||
self.max_filesize = data.get('max_filesize', '1024 ** 2 * 100') # Default 100 MB
|
self.max_filesize = data.get('max_filesize', '1024 ** 2 * 100') # Default 100 MB
|
||||||
self.base_url = data.get('base_url', 'http://localhost/f/')
|
self.base_url = data.get('base_url', 'http://localhost/f/')
|
||||||
|
self.frontend = data.get('frontend', False)
|
||||||
|
self.thumbnails = data.get('thumbnails', False)
|
||||||
|
self.thumbnail_path = data.get('thumbnail_path', '/data/thumbs')
|
||||||
|
self.thumbnail_strategy = data.get('thumbnail_strategy', 'both')
|
||||||
|
|
||||||
self.validate_config()
|
self.validate_config()
|
||||||
|
|
||||||
@ -52,6 +66,9 @@ class AppConfig:
|
|||||||
if not os.path.isdir(self.data_path):
|
if not os.path.isdir(self.data_path):
|
||||||
os.mkdir(self.data_path)
|
os.mkdir(self.data_path)
|
||||||
|
|
||||||
|
if not os.path.isdir(self.thumbnail_path):
|
||||||
|
os.mkdir(self.thumbnail_path)
|
||||||
|
|
||||||
self.base_url = f"{self.base_url.strip("/ \t\r\n")}"
|
self.base_url = f"{self.base_url.strip("/ \t\r\n")}"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -100,7 +117,7 @@ async def handle_upload(req):
|
|||||||
os.mkdir(f'{conf.data_path}')
|
os.mkdir(f'{conf.data_path}')
|
||||||
|
|
||||||
for _ in range(100):
|
for _ in range(100):
|
||||||
hb = os.urandom(conf.url_hash_len//2)
|
hb = os.urandom(conf.url_hash_len // 2)
|
||||||
h = hb.hex()
|
h = hb.hex()
|
||||||
if h not in file_db:
|
if h not in file_db:
|
||||||
break
|
break
|
||||||
@ -119,7 +136,11 @@ async def handle_upload(req):
|
|||||||
c = AES.new(conf.del_crypt_key, AES.MODE_CBC)
|
c = AES.new(conf.del_crypt_key, AES.MODE_CBC)
|
||||||
hb = Padding.pad(hb, AES.block_size)
|
hb = Padding.pad(hb, AES.block_size)
|
||||||
del_h = (c.encrypt(hb) + c.iv).hex()
|
del_h = (c.encrypt(hb) + c.iv).hex()
|
||||||
|
local_thname = f'{conf.thumbnail_path}/{h}_{filename}.png'
|
||||||
|
generate_thumbnail(local_fname, local_thname, ThumbnailOptions)
|
||||||
|
|
||||||
return web.Response(text=f'{{"file_link":"{conf.base_url}/{h}{ext}",'
|
return web.Response(text=f'{{"file_link":"{conf.base_url}/{h}{ext}",'
|
||||||
|
f'"thumb_link":"{conf.base_url}/thumb/{h}{ext}",'
|
||||||
f'"delete_link":"{conf.base_url}/del/{del_h}"}}', status=200)
|
f'"delete_link":"{conf.base_url}/del/{del_h}"}}', status=200)
|
||||||
|
|
||||||
os.unlink(local_fname)
|
os.unlink(local_fname)
|
||||||
@ -169,6 +190,18 @@ async def handle_download(req):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
async def handle_thumbnail(req):
|
||||||
|
fhash = req.match_info.get('hash', '').split('.', 1)[0]
|
||||||
|
if fhash not in file_db:
|
||||||
|
return web.Response(text='file not found', status=404)
|
||||||
|
|
||||||
|
## TODO: If thumbnail doesn't exist, generate new thumbnail
|
||||||
|
|
||||||
|
return web.FileResponse(f"{conf.thumbnail_path}/{fhash}_{file_db[fhash]}", headers={
|
||||||
|
hdrs.CONTENT_DISPOSITION: f'inline;filename="{file_db[fhash]}"'
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
for file in os.listdir(f"{conf.data_path}"):
|
for file in os.listdir(f"{conf.data_path}"):
|
||||||
try:
|
try:
|
||||||
@ -185,6 +218,7 @@ def main():
|
|||||||
app.router.add_post(base_path + '/post', handle_upload)
|
app.router.add_post(base_path + '/post', handle_upload)
|
||||||
app.router.add_get(base_path + '/del/{hash}', handle_delete)
|
app.router.add_get(base_path + '/del/{hash}', handle_delete)
|
||||||
app.router.add_get(base_path + '/{hash}', handle_download)
|
app.router.add_get(base_path + '/{hash}', handle_download)
|
||||||
|
app.router.add_get(base_path + '/thumb/{hash}', handle_thumbnail)
|
||||||
|
|
||||||
web.run_app(app, port=80)
|
web.run_app(app, port=80)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user