Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use stream in tauri-plugin-fs writeFile #1598

Closed
rwv opened this issue Jul 19, 2024 · 2 comments · Fixed by #1964
Closed

Use stream in tauri-plugin-fs writeFile #1598

rwv opened this issue Jul 19, 2024 · 2 comments · Fixed by #1964
Labels
plugin: fs Includes former "fs-extra" and "fs-watch" plugins question Further information is requested

Comments

@rwv
Copy link

rwv commented Jul 19, 2024

Describe the problem

For now I’m using

const dataBuffer = await blob.arrayBuffer();
const data = new Uint8Array(dataBuffer);
await writeFile(filename, data)

to write file.

Describe the solution you'd like

Can we use blob.stream to get a readable stream and pass it to writeFile. Since v2’s IPC is based on Response, we can use new Response() to generate a streaming response to improve performance and reduce memory usage.

Alternatives considered

Can Transferable object improve performance?

Additional context

No response

@rwv
Copy link
Author

rwv commented Jul 19, 2024

workaround:

import { writeFile, type WriteFileOptions } from "@tauri-apps/plugin-fs";

export async function writeFileFromStream(
  path: string | URL,
  stream: ReadableStream<Uint8Array>,
  options?: WriteFileOptions & { chunkSize?: number }
) {
  const chunkSize = options?.chunkSize ?? 1024 * 1024; // 1MB in bytes
  const reader = stream.getReader();

  let chunks: Uint8Array[] = [];
  let bytesRead = 0;

  // eslint-disable-next-line no-constant-condition
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    chunks.push(value);
    bytesRead += value.length;

    if (bytesRead >= chunkSize) {
      const chunk = new Uint8Array(bytesRead);
      let offset = 0;
      for (const chunkValue of chunks) {
        chunk.set(chunkValue, offset);
        offset += chunkValue.length;
      }

      await writeFile(path, chunk, {
        ...options,
        append: true,
      });
      chunks = [];
      bytesRead = 0;
    }
  }

  if (bytesRead > 0) {
    const chunk = new Uint8Array(bytesRead);
    let offset = 0;
    for (const chunkValue of chunks) {
      chunk.set(chunkValue, offset);
      offset += chunkValue.length;
    }
    await writeFile(path, chunk, {
      ...options,
      append: true,
    });
  }
}

@FabianLars FabianLars transferred this issue from tauri-apps/tauri Jul 30, 2024
@FabianLars FabianLars added question Further information is requested plugin: fs Includes former "fs-extra" and "fs-watch" plugins labels Jul 30, 2024
@amrbashir
Copy link
Member

amrbashir commented Oct 21, 2024

I have added support for it in #1964 but I think your workaround could be improved by using open and FileHandle.write APIs

const file = await open(path, options)
for await (const chunk of stream) {
  await file.write(chunk)
}
file.close()

this will stream the data, instead of writing it at one go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin: fs Includes former "fs-extra" and "fs-watch" plugins question Further information is requested
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants