File uploads
Handling files are no different from other parameters.
from ninja import NinjaAPI, File
from ninja.files import UploadedFile
@api.post("/upload")
def upload(request, file: UploadedFile = File(...)):
data = file.read()
return {'name': file.name, 'len': len(data)}
UploadedFile
is an alias to Django's UploadFile and has all the methods and attributes to access the uploaded file:
- read()
- multiple_chunks(chunk_size=None)
- chunks(chunk_size=None)
- name
- size
- content_type
- content_type_extra
- charset
- etc.
Uploading array of files
To upload several files at the same time, just declare a List
of UploadedFile
:
from typing import List
from ninja import NinjaAPI, File
from ninja.files import UploadedFile
@api.post("/upload-many")
def upload_many(request, files: List[UploadedFile] = File(...)):
return [f.name for f in files]
Uploading files with extra fields
Note: The HTTP protocol does not allow you to send files in application/json
format by default (unless you encode it somehow to JSON on client side)
To send files along with some extra attributes, you need to send bodies with multipart/form-data
encoding. You can do it by simply marking fields with Form
:
from ninja import NinjaAPI, Schema, UploadedFile, Form, File
from datetime import date
api = NinjaAPI()
class UserDetails(Schema):
first_name: str
last_name: str
birthdate: date
@api.post('/users')
def create_user(request, details: Form[UserDetails], file: File[UploadedFile]):
return [details.dict(), file.name]
Note: in this case all fields should be send as form fields
You can as well send payload in single field as JSON - just remove the Form mark from:
@api.post('/users')
def create_user(request, details: UserDetails, file: File[UploadedFile]):
return [details.dict(), file.name]
this will expect from the client side to send data as `multipart/form-data with 2 fields:
- details: JSON as string
- file: file
List of files with extra info
@api.post('/users')
def create_user(request, details: Form[UserDetails], files: File[list[UploadedFile]]):
return [details.dict(), [f.name for f in files]]