Closed feature request

A verb to upload a local file into a page file input

Glenn Jones · 6d ago ·closed by Colby Knox

We kept a list of tool issues as we worked on a project, the 772 power module (LM251772), a 4-layer board built with AI Flow on the Fusion lane, and set them aside so they wouldn't slow the build down. Now that the project is finished, we're filing them together. Some were seen on earlier versions; where we could, we checked that they still apply.

Use case: filling JLCPCB's quote form needs the Gerber zip uploaded to its <input type=file>. pup has no upload verb, so we base64-encoded the 214 KB zip, sent it to the page in 40 KB pup_eval chunks, built a File in the page, set it on the input through a DataTransfer and fired change. It worked, but it's slow, fragile, and won't scale to large files.

Request: something like pup_upload_file {selector, filePath} (Puppeteer's elementHandle.uploadFile / CDP DOM.setFileInputFiles), taking a path on the PC.

No design files attached; happy to describe more on request.

2 Replies

Colby Knox marked this in progress · 5d ago
Colby Knox · 5d ago

This is in pup 2.0.740 as pup_upload_file, on the insiders tier now.

pup_upload_file {"selector":"input[type=file]","filePath":"C:/Users/me/Downloads/gerbers.zip"}

What it does

  • Puts a file from the PC on the page's file input, with no OS dialog and in the background. Chrome reads the file from disk itself, so there is no base64 and no chunking.
  • selector can be the input (hidden is fine) or its Browse button or label. Open shadow roots and same-origin frames are searched. filePaths:[...] sends several files.
  • If the page creates its input when Browse is clicked: {armForNextChooser:true, filePath}, then pup_click the Browse control. The chooser is answered silently.
  • It checks the path first, reads the input back, and the page gets one input and one change per call, including a retry with the same file.
  • A missing file, two files on a single-file input and a disabled input are refused with a clear error. Chrome would otherwise accept the first two silently.
  • A file in your container goes to the PC with adom-bridge send_files first; the error tells you this if you pass a container path.

Paths it refuses: key, password and browser-login files (.pem, id_rsa, .env, .kdbx, Login Data), .ssh, .git and similar credential folders, AppData (except Temp), hidden folders in the home folder, system folders, other people's profiles and \\server paths. These come back as path_refused, and there is no override. To send one on purpose, copy it to an ordinary folder first. Downloads, Documents, Desktop, Temp and other drives are fine.

How it was tested (Windows, Chrome for Testing 157, both of pup's driving modes unless noted)

  • JLCPCB's quote form (extension mode), with a small three-layer test Gerber zip: the form answered "Detected 2 layer board of 20x20mm", which matches the file. No account and no order.
  • A real form post to a public upload test page: the site reported the file received.
  • A 5 GB file sent through Chrome to a local byte counter (extension mode): every byte arrived in 25 s, and Chrome stayed at 161 MB.
  • Hidden inputs, shadow roots, a label as the selector, a page that clears its input on change, the Browse chooser, an isolated window, and every refusal above.

Not tested

  • A multi-gigabyte upload to a real remote site. The 5 GB run went to a local counter.
  • A real board's Gerbers, or going past the JLCPCB quote step.
  • Inputs inside cross-origin iframes: the verb cannot look inside them, and it says so and points at the chooser route, which I did not try on such a page.
  • macOS: this verb is in the Windows build only.

Your real Chrome: nbrowser_set_file_input in nb 0.16.66 (insiders) does the same job. It had a bug where a page that uploads on change could send the file twice. That is fixed in extension 0.2.23, so refresh the loaded extension folder to get it. The same path rules apply. Tested in Chrome 156 with a throwaway profile.

How to upgrade: a desktop on the insiders tier picks up 2.0.740 by itself. Others get it when it is promoted to the public tier, which has not happened yet (public is on 2.0.723). If arming the chooser returns browser_needs_restart, run pup_restart_browser once.

Thanks for the clear report. Please reopen if it misbehaves on a real board.

Colby Knox closed this · 5d ago
Colby Knox · 5d ago

pup_upload_file is now on the public tier, in pup 2.0.741, so every desktop gets it with its next pup update. It works the same as described above.

Log in to reply.