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

[bug] When using tauri http to upload large files with formData, it's prone to crashing. #9508

Open
muwoo opened this issue Apr 19, 2024 · 1 comment
Labels
status: needs triage This issue needs to triage, applied to new issues type: bug

Comments

@muwoo
Copy link

muwoo commented Apr 19, 2024

Describe the bug

I need to upload a large file via tauri http by placing the file into formData, but it tends to crash easily when I upload it. I suspect it's because Tauri uses Body.form() to handle formData, and when handling files, Body.form() converts them to Unit8Array, which probably consumes a lot of memory when the file is large.

sourceCode: https://github.com/tauri-apps/tauri/blob/1.x/tooling/api/src/http.ts#L104-L109

async function formBody(data: FormInput): Promise<FormBody> {
  const form: FormBody = {}

  const append = async (
    key: string,
    v: string | Uint8Array | FilePart<Uint8Array> | File
  ): Promise<void> => {
    if (v !== null) {
      let r
      if (typeof v === 'string') {
        r = v
      } else if (v instanceof Uint8Array || Array.isArray(v)) {
        r = Array.from(v)
      } else if (v instanceof File) {
        r = {
          file: Array.from(new Uint8Array(await v.arrayBuffer())),
          mime: v.type,
          fileName: v.name
        }
      } else if (typeof v.file === 'string') {
        r = { file: v.file, mime: v.mime, fileName: v.fileName }
      } else {
        r = { file: Array.from(v.file), mime: v.mime, fileName: v.fileName }
      }
      form[String(key)] = r
    }
  }

  if (data instanceof FormData) {
    for (const [key, value] of data) {
      await append(key, value)
    }
  } else {
    for (const [key, value] of Object.entries(data)) {
      await append(key, value)
    }
  }

  return form
}

Reproduction

No response

Expected behavior

No response

Full tauri info output

[✔] Environment
    - OS: Mac OS 14.3.0 X64
    ✔ Xcode Command Line Tools: installed
    ✔ rustc: 1.76.0 (07dca489a 2024-02-04)
    ✔ cargo: 1.76.0 (c84b36747 2024-01-18)
    ✔ rustup: 1.26.0 (5af9b9484 2023-04-05)
    ✔ Rust toolchain: stable-aarch64-apple-darwin (default)
    - node: 16.13.0
    - pnpm: 7.33.7
    - yarn: 1.22.21
    - npm: 8.1.0

[-] Packages
    - tauri [RUST]: 1.6.1
    - tauri-build [RUST]: 1.5.0
    - wry [RUST]: 0.24.7
    - tao [RUST]: 0.16.5
    - @tauri-apps/api [NPM]: 1.5.3
    - @tauri-apps/cli [NPM]: 1.5.10

[-] App
    - build-type: bundle
    - CSP: unset
    - distDir: ../dist
    - devPath: http://localhost:1420/
    - framework: React
    - bundler: Rollup

Stack trace

No response

Additional context

No response

@muwoo muwoo added status: needs triage This issue needs to triage, applied to new issues type: bug labels Apr 19, 2024
@muwoo
Copy link
Author

muwoo commented Apr 19, 2024

Maybe the Tauri backend needs to convert the form_body into the format of Vec<u8>

let bytes: Vec<u8> = file.try_into()?;

https://github.com/tauri-apps/tauri/blob/1.x/core/tauri/src/api/http.rs#L144

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: needs triage This issue needs to triage, applied to new issues type: bug
Projects
None yet
Development

No branches or pull requests

1 participant