kopia lustrzana https://github.com/cirospaciari/socketify.py
64 wiersze
2.3 KiB
Markdown
64 wiersze
2.3 KiB
Markdown
![]() |
# Streaming data
|
||
|
You should never call res.end(huge buffer). res.end guarantees sending so backpressure will probably spike. Instead you should use res.try_end to stream huge data part by part. Use in combination with res.on_writable and res.on_aborted callbacks.
|
||
|
For simplicity, you can use `res.send_chunk`, this will return an Future and use `res.on_writable` and `res.on_aborted` for you.
|
||
|
|
||
|
Using send_chunk:
|
||
|
|
||
|
```python
|
||
|
async def home(res, req):
|
||
|
res.write_header("Content-Type", "audio/mpeg")
|
||
|
|
||
|
filename = "./file_example_MP3_5MG.mp3"
|
||
|
total = os.stat(filename).st_size
|
||
|
|
||
|
async with aiofiles.open(filename, "rb") as fd:
|
||
|
while not res.aborted:
|
||
|
buffer = await fd.read(16384) #16kb buffer
|
||
|
(ok, done) = await res.send_chunk(buffer, total)
|
||
|
if not ok or done: #if cannot send probably aborted
|
||
|
break
|
||
|
```
|
||
|
|
||
|
If you want to understand `res.send_chunk`, check out the implementation:
|
||
|
```python
|
||
|
def send_chunk(self, buffer, total_size):
|
||
|
self._chunkFuture = self.loop.create_future()
|
||
|
self._lastChunkOffset = 0
|
||
|
|
||
|
def is_aborted(self):
|
||
|
self.aborted = True
|
||
|
try:
|
||
|
if not self._chunkFuture.done():
|
||
|
self._chunkFuture.set_result(
|
||
|
(False, True)
|
||
|
) # if aborted set to done True and ok False
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
def on_writeble(self, offset):
|
||
|
# Here the timeout is off, we can spend as much time before calling try_end we want to
|
||
|
(ok, done) = self.try_end(
|
||
|
buffer[offset - self._lastChunkOffset : :], total_size
|
||
|
)
|
||
|
if ok:
|
||
|
self._chunkFuture.set_result((ok, done))
|
||
|
return ok
|
||
|
|
||
|
self.on_writable(on_writeble)
|
||
|
self.on_aborted(is_aborted)
|
||
|
|
||
|
if self.aborted:
|
||
|
self._chunkFuture.set_result(
|
||
|
(False, True)
|
||
|
) # if aborted set to done True and ok False
|
||
|
return self._chunkFuture
|
||
|
|
||
|
(ok, done) = self.try_end(buffer, total_size)
|
||
|
if ok:
|
||
|
self._chunkFuture.set_result((ok, done))
|
||
|
return self._chunkFuture
|
||
|
# failed to send chunk
|
||
|
self._lastChunkOffset = self.get_write_offset()
|
||
|
|
||
|
return self._chunkFuture
|
||
|
```
|