I use xterm.js to connect to a bash(a full-feature bash) and let user interact with the bash. I'd like support user to upload/download file through web terminal by using rz/sz.
If I connect to a machine' shell with SecureCRT/Xshell, I can upload/download files with rz/sz command. I'd like use zterm.js to connect to a machine's shell, and upload/download files with rz/sz command
Zmodem is a protocol feature of is the underlying serial line abstraction of the PTY system. This is already usable with tools like zssh in xterm.js. xterm.js itself is just forwarding the master IO of the PTY to the browser. In reality you are operating on the system where the xterm.js server part is hosted.
This is quite different to a terminal emulator operating on the same machine like SecureCRT does.
So the question is - From which machine to which machine do you want to move files through the terminal? (Remember your local machine has no terminal channel to the server part of xterm.js).
I'd like to move files from local machine to remote machine. The remote machine can not be accessed by local machine directly, since it has no external ip.
Remember your local machine has no terminal channel to the server part of xterm.js
Well you can use zssh (with zmodem support), sftp or scp from the proxy.
Unless someone implements it there is no way to up/download files directly from the webterminal in your browser to the remote machine. One of the modem protocols could be used that way (there is a XModem JS implementation), but since the browser has very limited filesystem access I question the usefulness. The hard part would be to provide a download interaction with the browser for big files (since the data is landing directly in the browser through the websocket, JS would have to hold all data until it can be saved.)
Another approach would be to enhance the server part with rz/sz functionality and map that transparently to the browser. This would circumvent the FS limitations of the browser but would need to hook another parser into the terminal stream to catch the 'rz\r' initialisation of the modem protocols.
I’ve been working on a ZMODEM implementation in JavaScript and have it transferring files in both directions via xterm.js.
The browser does indeed have to buffer the entire file when it receives. :( That’s really the only downside, though, and it’s not bad unless you’re sending very large files. Uploads can be done via FileReader, and downloads happen via the “download” attribute of <a> elements.
I’m still testing and documenting it, but is ZMODEM integration a feature that would interest xterm.js?
@FGasper Nice :) Sounds promising, if you implemented it with node's stream API it could also be useful for big files as a server side extension, that proxies those files to the browser endpoint via download link.
@parisk The X/Y/Z-MODEM protocols allow to "abuse" a terminal connection for direct file transfer from and to the other side. This is very useful if you want to orchestrate a server only through a single terminal session. For POSIX systems there are the rz/sz tools to accomplish this.
Well for xterm.js it is a perfect addon, it will raise the usefulness of xterm.js for server admins in restricted environments. 👍
NB: XMODEM and YMODEM both have the drawback of not “prompting” the other side that there’s a file transfer ready. (It’s unfortunate because they’re much simpler!)
ZMODEM sends what is essentially a “magic string” that can be watched for; then you prompt the user, “ZMODEM detected; proceed with file transfer?” At that point the implementation provides means either to provide files to transfer or to accept/skip files as the sender offers them.
Nice, works like a charm (tested with text files in Firefox).
Just a few remarks:
Is it possible to trigger the init sequence by accident (e.g. random data output)? If so, the terminal would IMHO need an "enter file transfer" setting to make this explicit.
The "Start ZMODEM session" should be interruptable, selecting "No" does not abort rz on the other end atm.
Is it possible to draw some progress bar / indicator into the terminal widget while the transfer is ongoing? Or some other more fancy stuff, atm rz/sz prints some weird status numbers into the terminal.
Yes, it’s possible to trigger the init sequence by accident. That’s what the “Start ZMODEM session” prompt is for: the user can still back out if needs be.
Should be fixed now.
The application receives progress events in sync with the browser’s FileReader API. Chrome seems to give content with progress; however, Firefox doesn’t actually give the file content in those events. If you send yourself a suitably large file in Chrome you’ll see something like:
The weird characters at the start of a session are the printable parts of the ZMODEM receive-init sequence: ** + ASCII CAN + B01 + 10 hex characters + CR + 0x8a + XON. I agree that it’s ugly that they go to the screen; however, it’s pretty standard in ZMODEM-savvy terminals that I’ve used. I suppose it could send enough BS characters to the terminal to delete those characters? Or maybe just filter them out if they do arrive together (as I’d think they generally will). (UPDATE: “Problem” with sending BS characters is that it’ll only happen after the user accepts ZMODEM; the characters have to show on the terminal first because the user hasn’t yet confirmed that ZMODEM is what’s desired.)
There’s also a need to add a control to cancel an in-progress transfer. I’m still looking at the best way to handle that.
Potentially. The spec isn’t always the most helpful thing; for example, it mentions an Attn sequence that is sent after a ZSINIT. The spec seems to suggest that that’s how to get a sender to pause a data send, but apparently nothing actually uses Attn. Likewise with the ESC8 option: it’s not actually implemented in lrzsz, and since that’s the de facto reference implementation, ESC8 is unusable—which is a shame because it would nicely work around that problem with the termios IEXTEN flag.
I’m in a bit of a time crunch on other projects right now but hope to return to this next week.
If I may add my two cents regarding the shape of this for making it an xterm plugin: I would propose to not add an UI at all, but to dispatch things through an event, similar to node streams. Something like
```javascript
term.on('transfer', (transfer) => {
// accept or reject the transfer
transfer.accept();
// listen for progress
transfer.on('progress', ...);
// data chunks arrive
transfer.on('data', ...);
// transfer has finished
transfer.once('end', ...);
// cancel transfer
transfer.abort();
});
```
This way a consumer can build its own UI on top of the plugin.
I’ve made an ALPHA release of zmodem.js. From here I’ll look at the plugin interface for xterm.js, but anyone who wants to look at zmodem.js, please feel free to do so and let me know how it works for you.
Activity
parisk commentedon Sep 20, 2016
Could you please get into some more details on how this would work on xterm.js?
mqliang commentedon Sep 20, 2016
I use xterm.js to connect to a bash(a full-feature bash) and let user interact with the bash. I'd like support user to upload/download file through web terminal by using rz/sz.
mqliang commentedon Sep 20, 2016
If I connect to a machine' shell with SecureCRT/Xshell, I can upload/download files with
rz/szcommand. I'd like use zterm.js to connect to a machine's shell, and upload/download files withrz/szcommandjerch commentedon Sep 20, 2016
Zmodem is a protocol feature of is the underlying serial line abstraction of the PTY system. This is already usable with tools like
zsshin xterm.js. xterm.js itself is just forwarding the master IO of the PTY to the browser. In reality you are operating on the system where the xterm.js server part is hosted.This is quite different to a terminal emulator operating on the same machine like SecureCRT does.
So the question is - From which machine to which machine do you want to move files through the terminal? (Remember your local machine has no terminal channel to the server part of xterm.js).
mqliang commentedon Sep 21, 2016
I'd like to move files from local machine to remote machine. The remote machine can not be accessed by local machine directly, since it has no external ip.
Is there any workaround for this?
jerch commentedon Sep 21, 2016
Well you can use zssh (with zmodem support), sftp or scp from the proxy.
Unless someone implements it there is no way to up/download files directly from the webterminal in your browser to the remote machine. One of the modem protocols could be used that way (there is a XModem JS implementation), but since the browser has very limited filesystem access I question the usefulness. The hard part would be to provide a download interaction with the browser for big files (since the data is landing directly in the browser through the websocket, JS would have to hold all data until it can be saved.)
Another approach would be to enhance the server part with rz/sz functionality and map that transparently to the browser. This would circumvent the FS limitations of the browser but would need to hook another parser into the terminal stream to catch the 'rz\r' initialisation of the modem protocols.
FGasper commentedon Sep 5, 2017
I’ve been working on a ZMODEM implementation in JavaScript and have it transferring files in both directions via xterm.js.
The browser does indeed have to buffer the entire file when it receives. :( That’s really the only downside, though, and it’s not bad unless you’re sending very large files. Uploads can be done via FileReader, and downloads happen via the “download” attribute of
<a>elements.I’m still testing and documenting it, but is ZMODEM integration a feature that would interest xterm.js?
jerch commentedon Sep 5, 2017
@FGasper Nice :) Sounds promising, if you implemented it with node's stream API it could also be useful for big files as a server side extension, that proxies those files to the browser endpoint via download link.
FGasper commentedon Sep 5, 2017
The library itself is platform-agnostic, so it should work anywhere. (Knock on wood.)
parisk commentedon Sep 7, 2017
@FGasper sounds neat 😄!
We can definitely consider a zmodem addon, if it works in the browser.
What are usually the use cases for using zmodem?
FGasper commentedon Sep 7, 2017
I use it to do file transfers within a terminal session to/from my workstation. It allows you not to have to scp/sftp or what not.
Similar to this for iTerm2:
https://github.com/mmastrac/iterm2-zmodem
jerch commentedon Sep 7, 2017
@parisk The X/Y/Z-MODEM protocols allow to "abuse" a terminal connection for direct file transfer from and to the other side. This is very useful if you want to orchestrate a server only through a single terminal session. For POSIX systems there are the
rz/sztools to accomplish this.Well for xterm.js it is a perfect addon, it will raise the usefulness of xterm.js for server admins in restricted environments. 👍
FGasper commentedon Sep 7, 2017
NB: XMODEM and YMODEM both have the drawback of not “prompting” the other side that there’s a file transfer ready. (It’s unfortunate because they’re much simpler!)
ZMODEM sends what is essentially a “magic string” that can be watched for; then you prompt the user, “ZMODEM detected; proceed with file transfer?” At that point the implementation provides means either to provide files to transfer or to accept/skip files as the sender offers them.
17 remaining items
FGasper commentedon Sep 15, 2017
I’ve got this into what I think is a reasonable state to try it out.
zmodembranch.git submodule init; git submodule updatenpm install(See below.)npm start, then loadlocalhost:3000in the browser. (Chrome is what I’ve tested.)lrzszinstalled.rz, and send one or more files from your workstation to the remote.sz <filename1> <filename2> …will send files in a batch to your workstation.(The UI is minimal by design; assumedly a “real” deployment would polish it more.)
Concerning step 4: When I tested just now on my workstation I had to fix a permissions issue with the
node-gyppackage.jerch commentedon Sep 18, 2017
Nice, works like a charm (tested with text files in Firefox).
Just a few remarks:
rzon the other end atm.rz/szprints some weird status numbers into the terminal.FGasper commentedon Sep 18, 2017
@jerch
Yes, it’s possible to trigger the init sequence by accident. That’s what the “Start ZMODEM session” prompt is for: the user can still back out if needs be.
Should be fixed now.
The application receives
progressevents in sync with the browser’s FileReader API. Chrome seems to give content withprogress; however, Firefox doesn’t actually give the file content in those events. If you send yourself a suitably large file in Chrome you’ll see something like:**+ ASCII CAN +B01+ 10 hex characters + CR + 0x8a + XON. I agree that it’s ugly that they go to the screen; however, it’s pretty standard in ZMODEM-savvy terminals that I’ve used.I suppose it could send enough BS characters to the terminal to delete those characters? Or maybe just filter them out if they do arrive together (as I’d think they generally will).(UPDATE: “Problem” with sending BS characters is that it’ll only happen after the user accepts ZMODEM; the characters have to show on the terminal first because the user hasn’t yet confirmed that ZMODEM is what’s desired.)There’s also a need to add a control to cancel an in-progress transfer. I’m still looking at the best way to handle that.
jerch commentedon Sep 20, 2017
Maybe this from the specs helps?
FGasper commentedon Sep 22, 2017
Potentially. The spec isn’t always the most helpful thing; for example, it mentions an Attn sequence that is sent after a ZSINIT. The spec seems to suggest that that’s how to get a sender to pause a data send, but apparently nothing actually uses Attn. Likewise with the ESC8 option: it’s not actually implemented in
lrzsz, and since that’s the de facto reference implementation, ESC8 is unusable—which is a shame because it would nicely work around that problem with the termios IEXTEN flag.I’m in a bit of a time crunch on other projects right now but hope to return to this next week.
mofux commentedon Sep 22, 2017
FGasper commentedon Sep 22, 2017
@mofux That’s how I would want this to work as well. The UI components that I’ve put into the demo are meant just to demonstrate the controls.
tsl0922 commentedon Sep 23, 2017
@FGasper Good job 👍
I'm going to add ZModem support for ttyd when your api is ready for use (tsl0922/ttyd#37), thanks for your work.
FGasper commentedon Oct 16, 2017
https://www.npmjs.com/package/zmodem.js
I’ve made an ALPHA release of zmodem.js. From here I’ll look at the plugin interface for xterm.js, but anyone who wants to look at zmodem.js, please feel free to do so and let me know how it works for you.
FGasper commentedon Nov 8, 2017
The ZMODEM addon is now merged, FYI.
zhengtulymGh commentedon Jun 23, 2018
win7 system
why can't open File Explorer?

alanhe421 commentedon May 29, 2022
The code is written very clearly, you can change it yourself.
just like this.
I forked demo https://github.com/alanhg/xterm.js
zhengtulymGh commentedon May 29, 2022