Ver código fonte

Potential implementation

Manav Rathi 1 ano atrás
pai
commit
243d019e8b
1 arquivos alterados com 41 adições e 4 exclusões
  1. 41 4
      desktop/src/main/stream.ts

+ 41 - 4
desktop/src/main/stream.ts

@@ -2,6 +2,7 @@
  * @file stream data to-from renderer using a custom protocol handler.
  */
 import { net, protocol } from "electron/main";
+import StreamZip from "node-stream-zip";
 import { createWriteStream, existsSync } from "node:fs";
 import fs from "node:fs/promises";
 import { Readable } from "node:stream";
@@ -34,17 +35,23 @@ export const registerStreamProtocol = () => {
     protocol.handle("stream", async (request: Request) => {
         const url = request.url;
         // The request URL contains the command to run as the host, and the
-        // pathname of the file as the path. For example,
+        // pathname of the file as the path. An additional path can be specified
+        // as the URL hash.
         //
-        //     stream://write/path/to/file
-        //              host-pathname-----
+        // For example,
         //
-        const { host, pathname } = new URL(url);
+        //     stream://write/path/to/file#/path/to/another/file
+        //              host[pathname----] [pathname-2---------]
+        //
+        const { host, pathname, hash } = new URL(url);
         // Convert e.g. "%20" to spaces.
         const path = decodeURIComponent(pathname);
+        const hashPath = decodeURIComponent(hash);
         switch (host) {
             case "read":
                 return handleRead(path);
+            case "read-zip":
+                return handleReadZip(path, hashPath);
             case "write":
                 return handleWrite(path, request);
             default:
@@ -88,6 +95,36 @@ const handleRead = async (path: string) => {
     }
 };
 
+const handleReadZip = async (zipPath: string, zipEntryPath: string) => {
+    try {
+        const zip = new StreamZip.async({
+            file: zipPath,
+        });
+        const entry = await zip.entry(zipEntryPath);
+        const stream = await zip.stream(entry);
+
+        return new Response(Readable.toWeb(new Readable(stream)), {
+            headers: {
+                // We don't know the exact type, but it doesn't really matter,
+                // just set it to a generic binary content-type so that the
+                // browser doesn't tinker with it thinking of it as text.
+                "Content-Type": "application/octet-stream",
+                "Content-Length": `${entry.size}`,
+                // !!TODO(MR): Is this ms
+                "X-Last-Modified-Ms": `${entry.time}`,
+            },
+        });
+    } catch (e) {
+        log.error(
+            `Failed to read entry ${zipEntryPath} from zip file at ${zipPath}`,
+            e,
+        );
+        return new Response(`Failed to read stream: ${e.message}`, {
+            status: 500,
+        });
+    }
+};
+
 const handleWrite = async (path: string, request: Request) => {
     try {
         await writeStream(path, request.body);