Skip to content

Commit 28cf121

Browse files
Merge pull request #820 from MasoniteFramework/feature/add-response-streams
Feature/add response streams
2 parents 7956736 + a76a015 commit 28cf121

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

src/masonite/response/response.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import mimetypes
55
from pathlib import Path
66
from typing import TYPE_CHECKING, Any
7+
import types
78

89
if TYPE_CHECKING:
910
from ..foundation import Application
@@ -119,6 +120,8 @@ def data(self) -> bytes:
119120
"""Get the response content as bytes."""
120121
if isinstance(self.content, str):
121122
return bytes(self.content, "utf-8")
123+
if isinstance(self.content, types.GeneratorType):
124+
return b"".join(self.content)
122125

123126
return self.content
124127

@@ -137,6 +140,10 @@ def view(self, view: Any, status: int = 200) -> "bytes|Response":
137140
view, status = view
138141
self.status(status)
139142

143+
if isinstance(view, types.GeneratorType):
144+
self.status(status)
145+
return self
146+
140147
if not self.get_status_code():
141148
self.status(status)
142149

@@ -218,3 +225,28 @@ def download(self, name: str, location: str, force: bool = False) -> "Response":
218225
data = filelike.read()
219226

220227
return self.view(data)
228+
229+
def stream(self, name: str, location: str, force: bool = True, chunk_size: int = 8192) -> "Response":
230+
"""Set the response as a file download response using streaming."""
231+
self.status(200)
232+
233+
# Set content type and disposition headers
234+
self.header_bag.add(Header("Content-Type", "application/octet-stream"))
235+
self.header_bag.add(Header("Content-Disposition", f'attachment; filename="{name}{Path(location).suffix}"'))
236+
237+
# Get the file size and set the Content-Length header
238+
file_size = Path(location).stat().st_size
239+
self.header_bag.add(Header("Content-Length", str(file_size)))
240+
241+
# Define the generator to stream the file in chunks
242+
def file_generator():
243+
with open(location, "rb") as file:
244+
while True:
245+
chunk = file.read(chunk_size)
246+
if not chunk:
247+
break
248+
yield chunk
249+
250+
# Set the response content as the file generator and return
251+
self.content = file_generator()
252+
return self

0 commit comments

Comments
 (0)