Usage¶
Default¶
To allow upload files to ../uploads
directory for all clients via /uploads
URL,
from pathlib import Path
from aiohttp import web
from aiohttp_tus import setup_tus
app = setup_tus(
web.Application(),
upload_path=Path(__file__).parent.parent / "uploads",
)
Understanding tus.io Chunk Size¶
By default, Uppy and some other tus.io clients do not setup chunk
size and tries to upload as large chunk, as possible. However as
aiohttp.web.Application
setting up client_max_size
on app initialization
you might need to configure server to receive larger chunks as well as setup tus.io
client to use respected chunk sizes.
Examples below shown on how to config different parts to upload files with chunk size
of 4MB (4_000_000
bytes)
aiohttp.web configuration¶
from aiohttp import web
from aiohttp_tus import setup_tus
app = web.Application(client_max_size=4_000_000)
nginx configuration¶
location ~ ^/uploads.*$ {
client_max_body_size 4M;
proxy_pass http://localhost:8080;
}
tus.py configuration¶
tus-upload --chunk-size=4000000 \
/path/to/large-file http://localhost:8080/uploads
uppy.io Configuration¶
uppy.use(Uppy.Tus, {
endpoint: "http://localhost:8080/uploads",
chunkSize: 3999999
})
Important
To make Uppy.Tus plugin work you need to specify
chunk size at least 1 byte smaller than client_max_size
. If you’ll provide
chunk size equals to client max size upload will not work properly.
CORS Headers¶
At a moment (May 17 2020), aiohttp-tus
supports setting up CORS Headers for
aiohttp.web
application only via cors_middleware
from aiohttp-middlewares package.
As aiohttp-tus
registers OPTIONS handlers it doesn’t work with
aiohttp-cors library cause of known issue
aio-libs/aiohttp-cors#241.
(Full discussion)
To enable CORS Headers for your aiohttp.web
application, which is using
aiohttp-tus
, you need to,
Install aiohttp-middlewares
In your app.py,
from pathlib import Path from aiohttp import web from aiohttp_middlewares import cors_middleware from aiohttp_tus import setup_tus # Allow CORS Headers for requests from http://localhost:3000 app = web.Application( middlewares=( cors_middleware(origins=("http://localhost:3000",)), ) ) setup_tus( app, upload_path=Path(__file__).parent.parent / "uploads", )
Reverse proxy and HTTPS¶
When aiohttp web application with aiohttp-tus
deployed under the reverse proxy
(such as nginx), with HTTPS support you need to setup
https_middleware
from aiohttp-middlewares package to ensure that aiohttp.web.Request
instance has proper schema.
To use HTTPS middleware you need to,
Install aiohttp-middlewares
In app.py,
from pathlib import Path from aiohttp import web from aiohttp_middlewares import https_middleware from aiohttp_tus import setup_tus app = web.Application(middlewares=(https_middleware(),)) setup_tus( app, upload_path=Path(__file__).parent.parent / "uploads" )
User Uploads¶
To allow upload files to /files/{username}
directory only for authenticated users
via /users/{username}/uploads
URL,
from aiohttp_tus.annotations import Handler
def upload_user_required(handler: Handler) -> Handler:
async def decorator(request: web.Request) -> web.Response:
# Change ``is_user_authenticated`` call to actual call,
# checking whether user authetnicated for given request
# or not
if not is_user_authenticated(request):
raise web.HTTPForbidden()
return await handler(request)
return decorator
app = setup_tus(
web.Application(),
upload_path=Path("/files") / r"{username}",
upload_url=r"/users/{username}/uploads",
decorator=upload_user_required,
)
On Upload Done Callback¶
There is a possibility to run any coroutine after upload is done. Example below, illustrates how to achieve that,
from aiohttp_tus.data import Resource
async def notify_on_upload(
request: web.Request, resource: Resource, file_path: Path,
) -> None:
redis = request.config_dict["redis"]
await redis.rpush("uploaded_files", resource.file_name)
app = setup_tus(
web.Application(),
upload_path=Path(__file__).parent.parent / "uploads",
on_upload_done=notify_on_upload,
)
Mutliple TUS upload URLs¶
It is possible to setup multiple TUS upload URLs. Example below illustrates, how to
achieve anonymous & authenticated uploads in same time for one
aiohttp.web.Application
instance.
app = web.Application()
base_upload_path = Path(__file__).parent.parent / "uploads"
# Anonymous users uploads
setup_tus(app, upload_path=base_upload_path / "anonymous")
# Authenticated users uploads
setup_tus(
app,
upload_path=base_upload_path / r"{username}",
upload_url=r"/users/{username}/uploads",
decorator=upload_user_required,
)
Upload resource name¶
In most cases there is no need to specify aiohttp.web.Resource
name for upload
resource, but when it is necessary, it is possible to specify custom
upload_resource_name
and lately use it for URL reversing.
Example below illustrates how to achieve it,
In app.py
,
setup_tus(
web.Application(),
upload_path=(
Path(__file__).parent.parent / "uploads" / r"{username}"
),
upload_url="/user/{username}/uploads",
upload_resource_name="user_upload",
)
In views.py
,
async def user_profile(request: web.Request) -> web.Response:
upload_url = request.app.router["uploads"].url_for(
username=request.match_info["username"]
)
return aiohttp_jinja2.render(
"users/profile.html",
request,
{"upload_url": upload_url},
)