`UploadFile` has the following `async` methods. They all call the corresponding file methods underneath (using the internal `SpooledTemporaryFile`).
-* `async write(data)`: Writes `data` (`str` or `bytes`) to the file.
-* `async read(size)`: Reads `size` (`int`) bytes/characters of the file.
+* `async write(data)`: Writes `data` (`bytes`) to the file.
+* `async read(size)`: Reads `size` (`int`) bytes of the file.
* `async seek(offset)`: Goes to the byte position `offset` (`int`) in the file.
* E.g., `await myfile.seek(0)` would go to the start of the file.
* `async close()`: Closes the file.
"""
spool_max_size = 1024 * 1024
+ file: typing.BinaryIO
headers: "Headers"
def __init__(
self,
filename: str,
- file: typing.IO = None,
+ file: typing.Optional[typing.BinaryIO] = None,
content_type: str = "",
*,
headers: "typing.Optional[Headers]" = None,
self.filename = filename
self.content_type = content_type
if file is None:
- file = tempfile.SpooledTemporaryFile(max_size=self.spool_max_size)
- self.file = file
+ self.file = tempfile.SpooledTemporaryFile(max_size=self.spool_max_size) # type: ignore # noqa: E501
+ else:
+ self.file = file
self.headers = headers or Headers()
@property
rolled_to_disk = getattr(self.file, "_rolled", True)
return not rolled_to_disk
- async def write(self, data: typing.Union[bytes, str]) -> None:
+ async def write(self, data: bytes) -> None:
if self._in_memory:
self.file.write(data) # type: ignore
else:
await run_in_threadpool(self.file.write, data)
- async def read(self, size: int = -1) -> typing.Union[bytes, str]:
+ async def read(self, size: int = -1) -> bytes:
if self._in_memory:
return self.file.read(size)
return await run_in_threadpool(self.file.read, size)
await big_file.close()
+@pytest.mark.anyio
+async def test_upload_file_file_input():
+ """Test passing file/stream into the UploadFile constructor"""
+ stream = io.BytesIO(b"data")
+ file = UploadFile(filename="file", file=stream)
+ assert await file.read() == b"data"
+ await file.write(b" and more data!")
+ assert await file.read() == b""
+ await file.seek(0)
+ assert await file.read() == b"data and more data!"
+
+
def test_formdata():
upload = io.BytesIO(b"test")
form = FormData([("a", "123"), ("a", "456"), ("b", upload)])