]> git.ipfire.org Git - pbs.git/commitdiff
packages: Fix viewing and downloading files
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 10 Mar 2023 16:54:11 +0000 (16:54 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 10 Mar 2023 16:54:11 +0000 (16:54 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/buildservice/packages.py
src/web/__init__.py
src/web/packages.py

index 19e8969418d626d0a89b4246796da58328a3904c..95f66f6475095a7721c228887cae4e8880ad724a 100644 (file)
@@ -635,12 +635,10 @@ class File(base.Object):
 
                return type or "application/octet-stream"
 
-       # Payload
+       # Send Payload
 
-       async def get_payload(self):
-               """
-                       Fetches and returns the payload
-               """
+       @property
+       async def payload(self):
                # Open the package
                p = await self.package.open()
 
@@ -649,3 +647,18 @@ class File(base.Object):
 
                # Read the payload in a separate thread
                return await asyncio.to_thread(func)
+
+       async def sendfile(self, f, chunk_size=102400):
+               """
+                       Sends the payload of the file into the given file descriptor
+               """
+               # XXX This should ideally not load the entire payload into memory at once
+
+               # Fetch the payload
+               payload = await self.payload
+
+               # Send the payload in chunks, so that we do not overwhelm Tornado
+               for i in range(0, self.size, chunk_size):
+                       block = payload[i:i+chunk_size]
+
+                       f.write(block)
index d2095ec89a9f87cd2ed3034a0a4adf0ad4c8d907..005c0c49a39fda3faabd67a0b4884ec7c02623a8 100644 (file)
@@ -115,9 +115,9 @@ class Application(tornado.web.Application):
                        (r"/packages", packages.IndexHandler),
                        (r"/packages/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", packages.ShowHandler),
                        (r"/packages/([\w\-\+]+)", packages.NameHandler),
-                       (r"/package/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/download(.*)",
+                       (r"/packages/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/download(.*)",
                                packages.FileDownloadHandler),
-                       (r"/package/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/view(.*)",
+                       (r"/packages/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/view(.*)",
                                packages.FileViewHandler),
 
                        # Builds
index a0f4ab35036f59f219e1976f2fd74ad2f7874582..b828f73b510ce9c70165f68157a0b501aa1192ab 100644 (file)
@@ -69,19 +69,13 @@ class FileDownloadHandler(base.BaseHandler):
 
                # Send the filename
                self.set_header("Content-Disposition",
-                       "attachment; filename=%s" % os.path.basename(file.name))
+                       "attachment; filename=%s" % os.path.basename(file.path))
 
                # These pages should not be indexed
                self.add_header("X-Robots-Tag", "noindex")
 
-               # XXX this should probably not be done in one large operation.
-               # Instead we should send the file chunk by chunk.
-
-               # Fetch the payload
-               payload = await file.get_payload()
-
-               # Send the payload to the client
-               self.finish(payload)
+               # Send the payload
+               await file.sendfile(self)
 
 
 class FileViewHandler(base.BaseHandler):
@@ -102,10 +96,8 @@ class FileViewHandler(base.BaseHandler):
                # These pages should not be indexed
                self.add_header("X-Robots-Tag", "noindex")
 
-               # Fetch payload
-               payload = await file.get_payload()
-
-               self.render("packages/view-file.html", package=package, file=file, payload=payload)
+               self.render("packages/view-file.html", package=package,
+                       file=file, payload=await file.payload)
 
 
 class DependenciesModule(ui_modules.UIModule):