Compare commits
35
Commits
main
..
c6386eb794
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6386eb794 | ||
|
|
bad8e011ce | ||
|
|
78874deb56 | ||
|
|
0b958e3800 | ||
|
|
49f69cb688 | ||
|
|
9600f64eb9 | ||
|
|
ec489ab30f | ||
|
|
304d163464 | ||
|
|
a51c3739c9 | ||
|
|
a7aabcd36f | ||
|
|
03c8fb02a7 | ||
|
|
3ee5232f49 | ||
|
|
fb2a733f4c | ||
|
|
85fe10b7cd | ||
|
|
235cdc628b | ||
|
|
8bfa141a85 | ||
|
|
36ef6d7e4d | ||
|
|
9209e43b8b | ||
|
|
28300cb055 | ||
|
|
a875616522 | ||
|
|
37b9907334 | ||
|
|
d79664fdc5 | ||
|
|
ad1243afb7 | ||
|
|
d6d31a0500 | ||
|
|
983d4d668f | ||
|
|
2f6ecfe06d | ||
|
|
254cb6004b | ||
|
|
e0fcf53788 | ||
|
|
456e3c0823 | ||
|
|
5f518c8df7 | ||
|
|
15869d6537 | ||
|
|
3bd46cb640 | ||
|
|
1ed30e0d80 | ||
|
|
67d91a42e5 | ||
|
|
3e72ecab20 |
+1
-1
@@ -1,4 +1,4 @@
|
||||
.history
|
||||
.venv
|
||||
src/rupload/__pycache__
|
||||
src/upload/__pycache__
|
||||
uploads/*
|
||||
@@ -5,10 +5,10 @@ Easiest file manager for your server made for public use.
|
||||
It doesn't have captcha or whatsoever. It's designed for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, that's it's only security. Rate limiting is in consideration. The default file size is 50Mb. The default storage quota for whole directory is 10Gb. Default config will prevent your server for heavy abuse.
|
||||
|
||||
## Installation
|
||||
1. `make ensure_venv`
|
||||
2. `make install`
|
||||
3. `source ./.venv/bin/activate`
|
||||
4. `rupload.serve` (See parameters below. Running with default config using no parameters works too.)
|
||||
```
|
||||
python3 -m venv .venv
|
||||
./venv/bin/python -m pip install .
|
||||
```
|
||||
|
||||
## Usage
|
||||
```bash
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
@@ -16,7 +16,6 @@ python_requires = >=3.7
|
||||
install_requires =
|
||||
aiohttp==3.10.10
|
||||
dataset==1.6.2
|
||||
pillow
|
||||
|
||||
[options.packages.find]
|
||||
where = src
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Metadata-Version: 2.4
|
||||
Metadata-Version: 2.1
|
||||
Name: rupload
|
||||
Version: 1.3.37
|
||||
Summary: upload tool
|
||||
@@ -9,7 +9,6 @@ Requires-Python: >=3.7
|
||||
Description-Content-Type: text/markdown
|
||||
Requires-Dist: aiohttp==3.10.10
|
||||
Requires-Dist: dataset==1.6.2
|
||||
Requires-Dist: pillow
|
||||
|
||||
# RUpload
|
||||
|
||||
@@ -18,10 +17,10 @@ Easiest file manager for your server made for public use.
|
||||
It doesn't have captcha or whatsoever. It's designed for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, that's it's only security. Rate limiting is in consideration. The default file size is 50Mb. The default storage quota for whole directory is 10Gb. Default config will prevent your server for heavy abuse.
|
||||
|
||||
## Installation
|
||||
1. `make ensure_venv`
|
||||
2. `make install`
|
||||
3. `source ./.venv/bin/activate`
|
||||
4. `rupload.serve` (See parameters below. Running with default config using no parameters works too.)
|
||||
```
|
||||
python3 -m venv .venv
|
||||
./venv/bin/python -m pip install .
|
||||
```
|
||||
|
||||
## Usage
|
||||
```bash
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
aiohttp==3.10.10
|
||||
dataset==1.6.2
|
||||
pillow
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+30
-72
@@ -1,20 +1,16 @@
|
||||
import pathlib
|
||||
|
||||
import aiohttp
|
||||
from aiohttp import web
|
||||
|
||||
MAX_FILE_SIZE = 1024 * 1024 * 300 # 50Mb
|
||||
UPLOAD_FOLDER_QUOTA = 10 * 1024 * 1024 * 1024 # 10Gb
|
||||
UPLOAD_URL = "/"
|
||||
UPLOAD_PATH = "uploads"
|
||||
import asyncio
|
||||
import pathlib
|
||||
|
||||
|
||||
class Rupload(web.Application):
|
||||
def __init__(
|
||||
self,
|
||||
upload_url: str = UPLOAD_URL,
|
||||
upload_path: str = UPLOAD_PATH,
|
||||
max_file_size: int = MAX_FILE_SIZE,
|
||||
upload_folder_quota: int = UPLOAD_FOLDER_QUOTA,
|
||||
upload_url: str = "/uploads/",
|
||||
upload_path: str = "uploads",
|
||||
max_file_size: int = 1024 * 1024 * 50,
|
||||
upload_folder_quota: int = 10 * 1024 * 1024 * 1024,
|
||||
):
|
||||
self.upload_path = upload_path.rstrip("/")
|
||||
self.max_file_size = max_file_size
|
||||
@@ -35,22 +31,17 @@ UPLOAD_PAGE = """
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9">
|
||||
<title>RUpload 1.33.7</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>File Upload</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
background-color: #111111;
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f9;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
word-break: break-all;
|
||||
|
||||
margin: 0;
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.container {
|
||||
@@ -61,10 +52,7 @@ UPLOAD_PAGE = """
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
}
|
||||
.container-images {
|
||||
|
||||
filter: invert(1);
|
||||
}
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
margin-bottom: 20px;
|
||||
@@ -73,7 +61,6 @@ UPLOAD_PAGE = """
|
||||
|
||||
h2 {
|
||||
font-size: 20px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
color: #333;
|
||||
clear: both;
|
||||
@@ -123,9 +110,8 @@ UPLOAD_PAGE = """
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
object-fit: cover;
|
||||
margin: 3px;
|
||||
margin: 10px;
|
||||
float:left;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -140,9 +126,9 @@ UPLOAD_PAGE = """
|
||||
<button type="submit">Upload</button>
|
||||
</form>
|
||||
<br />
|
||||
Click <a href="#files">here</a> to see <a href="#files">uploaded files</a> (non-image) at the bottom of this page.
|
||||
Click <a href="#files">here</a> to see <a href="#files">uploaded files</a> (non-image) at the bottom of this page.<br />
|
||||
<h2>Uploaded images:</h2>
|
||||
<div class="container-images">
|
||||
<div class="container-image">
|
||||
[images_html]
|
||||
</div>
|
||||
<h2 id="files">Uploaded files:</h2>
|
||||
@@ -174,14 +160,12 @@ def format_size(size):
|
||||
def get_images(path):
|
||||
images = []
|
||||
for image in pathlib.Path(path).iterdir():
|
||||
if image.is_file() and image.suffix.lower() in [
|
||||
if image.is_file() and image.suffix in [
|
||||
".png",
|
||||
".jpg",
|
||||
".gif",
|
||||
".jpeg",
|
||||
".bmp",
|
||||
".webp",
|
||||
".svg",
|
||||
]:
|
||||
images.append(image)
|
||||
return images
|
||||
@@ -200,8 +184,7 @@ def create_images_html(url, image_paths):
|
||||
images_html = ""
|
||||
for image_path in image_paths:
|
||||
path = url.rstrip("/") + "/" + image_path.name
|
||||
thumbnail_path = "/thumbnail/" + url.strip("/") + "/" + image_path.name
|
||||
images_html += f'<a href="{path}"><img class="thumbnail" src="{thumbnail_path}" alt="{image_path.name}" /></a>\n'
|
||||
images_html += f'<img class="thumbnail" src="{path}" alt="{image_path.name}">'
|
||||
return images_html
|
||||
|
||||
|
||||
@@ -209,7 +192,7 @@ def create_files_html(url, file_paths):
|
||||
files_html = ""
|
||||
for file_path in file_paths:
|
||||
path = url.rstrip("/") + "/" + file_path.name
|
||||
files_html += f'<a href="{path}">{file_path.name}</a> ({format_size(file_path.stat().st_size)})\n<br>\n'
|
||||
files_html += f'<a href="{path}">{file_path.name}</a> ({format_size(file_path.stat().st_size)})<br>'
|
||||
return files_html
|
||||
|
||||
|
||||
@@ -254,7 +237,9 @@ async def handle_upload(request: web.Request):
|
||||
print(f"File {filename} deleted.")
|
||||
return web.Response(
|
||||
status=413,
|
||||
text=f"File is too large. Maximum file size is {app.max_file_size} bytes.",
|
||||
text="File is too large. Maximum file size is {} bytes.".format(
|
||||
app.max_file_size
|
||||
),
|
||||
)
|
||||
f.write(chunk)
|
||||
print(f"File {filename} uploaded successfully.")
|
||||
@@ -268,27 +253,6 @@ async def handle_upload(request: web.Request):
|
||||
return web.Response(status=400, text="No file uploaded.")
|
||||
|
||||
|
||||
async def handle_thumbnail(request: web.Request):
|
||||
path = request.match_info["path"]
|
||||
|
||||
safe_path = pathlib.Path(request.app.upload_path).joinpath(pathlib.Path(path).name)
|
||||
|
||||
if not safe_path.is_file():
|
||||
return web.Response(status=400, text="Invalid file type.")
|
||||
|
||||
|
||||
thumbnail_path = pathlib.Path(request.app.upload_path).joinpath(".thumbnail").joinpath(pathlib.Path(safe_path).name)
|
||||
if not thumbnail_path.parent.exists():
|
||||
thumbnail_path.parent.mkdir(exist_ok=True,parents=False)
|
||||
|
||||
if not thumbnail_path.exists():
|
||||
from PIL import Image
|
||||
image = Image.open(safe_path)
|
||||
image.thumbnail((200, 200))
|
||||
image.save(thumbnail_path)
|
||||
|
||||
return web.FileResponse(thumbnail_path)
|
||||
|
||||
async def handle_index(request: web.Request):
|
||||
image_paths = get_images(request.app.upload_path)
|
||||
images_html = create_images_html(
|
||||
@@ -302,14 +266,10 @@ async def handle_index(request: web.Request):
|
||||
if request.app.is_upload_folder_quota_reached:
|
||||
message = "Server reached quota! Contact administrator."
|
||||
if "is available here: " in message:
|
||||
url = message[message.find("here: ") + len("here: ") :]
|
||||
message = message[: message.find("here: ") + len("here: ")]
|
||||
message += f'<a href="{url}">'
|
||||
url = message[message.find("here: ") + len("here: "):]
|
||||
message = message[: message.find("here: ")+len("here: ")]
|
||||
message += f"<a href=\"{url}\">"
|
||||
message += f"{url}</a>"
|
||||
if not message:
|
||||
message = (
|
||||
"Any file type is allowed thus also binary/executable or source files."
|
||||
)
|
||||
if message:
|
||||
message += "<br /><br />"
|
||||
html_content = html_content.replace("[message]", message)
|
||||
@@ -317,10 +277,10 @@ async def handle_index(request: web.Request):
|
||||
|
||||
|
||||
def create_app(
|
||||
upload_url: str = UPLOAD_URL,
|
||||
upload_path: str = UPLOAD_PATH,
|
||||
max_file_size: int = MAX_FILE_SIZE,
|
||||
upload_folder_quota: int = UPLOAD_FOLDER_QUOTA,
|
||||
upload_url: str = "/",
|
||||
upload_path: str = "upload",
|
||||
max_file_size: int = 1024 * 1024 * 50,
|
||||
upload_folder_quota: int = 10 * 1024 * 1024 * 1024,
|
||||
):
|
||||
app = Rupload(
|
||||
upload_url=upload_url,
|
||||
@@ -330,12 +290,10 @@ def create_app(
|
||||
)
|
||||
pathlib.Path(upload_path).mkdir(parents=True, exist_ok=True)
|
||||
app.add_routes(
|
||||
[
|
||||
[
|
||||
web.get("/", handle_index),
|
||||
web.post("/upload", handle_upload),
|
||||
web.static("/", upload_path),
|
||||
web.get("/thumbnail/{path:.*}", handle_thumbnail),
|
||||
web.static("/uploads", upload_path),
|
||||
]
|
||||
)
|
||||
return app
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import argparse
|
||||
|
||||
from aiohttp import web
|
||||
|
||||
from rupload.app import create_app
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user