SFTP Upload in ASCII Mode
The Firezilla wiki has a page on technical specifications. The most widely implemented version of the SFTP spec is version 3 draft 2. Notably, the Openssh SFTP client and server implement that version of the spec.
Version 3 of the SFTP protocol doesn't have a feature equivalent to FTP's ASCII transfer mode. It always transfers files verbatim.
Later versions of the SFTP protocol support transfer modes that convert line terminator characters. Hypothetically, you could find a client and server that supports the feature.
Is this a matter of what SFTP protocol version the client is using...?
I don't know FireFTP's capabilities. But the OpenSSH SFTP server doesn't support an ASCII-like transfer mode.
is it simply "accepted" that when transferring a file from Windows -> Unix that you will have the additional CR (^M) leftover...
There are various ways of dealing with the issue. There are programs to convert from one format to another. Some programs that read text files will tolerate line terminators in either format.
How to set the transfer mode to ASCII in SFTP (version 3) using Perl
Using Net::SFTP::Foreign:
$sftp->put($local_from, $remote_to, conversion => 'unix2dos');
See On the fly data conversion.
ASCII mode in SFTP transfers
Quoting SFTP specification regarding text (aka ASCII) access to remote files:
5.3. Determining Server Newline Convention
In order to correctly process text files in a cross platform
compatible way, newline sequences must be converted between client
and server conventions.The SSH_FXF_TEXT_MODE file open flag (Section 8.1.1) makes it
possible to request that the server translate a file to a 'canonical'
wire format. This format uses CRLF as the line separator.Servers for systems using other conventions MUST translate to and
from the canonical form.
Note that the "text mode" is supported since SFTP version 4 only. Many existing SFTP implementations (including the most widespread one, the OpenSSH) support SFTP version 3 only. So they do not support text/ASCII mode at all.
How does Apache Camel support ASCII mode file transfer with SFTP?
The documentation is most likely false.
Both the
FtpEndpointConfigurer
and theSftpEndpointConfigurer
indeed propagate thebinary
parameter toFtpConfiguration.setBinary
andSftpConfiguration.setBinary
respectively. So in that sense, both support that parameter.But while
FtpOperations
queriesFtpConfiguration.isBinary
and setsFtpClient
mode accordingly:client.setFileType(configuration.isBinary() ? FTP.BINARY_FILE_TYPE : FTP.ASCII_FILE_TYPE);
... the
SftpConfiguration.isBinary
is never called. So the configured value is never used.
Is PuTTY (PSFTP) using binary mode to transfer a file in from some server to Windows client?
The PSFTP uses an SFTP protocol version 3.
In the SFTP protocol version 3 there are no transfer modes. Or in other words, there's only a binary transfer mode.
If you need "ascii download", you need to convert the downloaded file to Windows format after you download it with PSFTP.
Or use another Windows SFTP client that can do it for you.
For example WinSCP SFTP client supports the "ascii download".
If the server supports SFTP version 4 or newer, that supports "ascii download" natively, it uses that. If not, WinSCP converts the file after download automatically.
This is a simple batch file (.bat
) to download a file in ascii mode in WinSCP:
winscp.com /log="c:\path\sftp.log" /command ^
"open sftp://username:password@example.com/" ^
"get -transfer=ascii /remote/path/file.txt c:\local\path\file.txt" ^
"exit"
For details see:
- guide to WinSCP scripting and
- guide to converting PSFTP script to WinSCP script.
(I'm the author of WinSCP)
How to set file type and file transfer mode in JSch?
First of all, it is not clear from your question, whether you are aware that JSch and Apache Commons Net FtpClient
each use completely different and unrelated protocols. JSch is an SSH/SFTP client, while FtpClient
is an FTP client.
JSch uses an SFTP protocol version 3.
In the SFTP protocol version 3, there are no transfer modes. Or in other words, there is only the binary transfer mode.
And even if JSch used a newer version of SFTP protocol, which supports the ascii mode, the binary mode is the default anyway in SFTP.
So you do not have to do anything.
This is in a contrast to the FTP protocol, which defaults to the ascii mode. So you have explicitly switch to the binary mode with FTP (using the FTPClient.setFileType
in case of the Apache Commons Net).
As for the FTPClient.setFileTransferMode
– Your FTP code is wrong. The method accepts one of the *_TRANSFER_MODE
constants. Never the *_FILE_TYPE
. If you use BINARY_FILE_TYPE
, it results in sending an invalid MODE I
command to the server. Which for sure fails, and consequently has no effect at all. Check the method result code, it for sure returns false
.
Remove the call from your FTP code. There is no need to call FTPClient.setFileTransferMode
. Apache Commons Net supports only the default "stream" mode anyway (and most FTP servers do not support any other mode either).
Note the confusion in the names. The ascii/binary are commonly indeed called "transfer modes". But in FTP protocol specification (section 3.1.1 of RFC 959), they are actually called "data types" and are governed using TYPE
command.
While what FTP specification calls "transmission modes", governed by MODE
command (section 3.4), are completely different kind of modes: stream/block/compressed. They are hardly ever set or even mentioned.
As Apache Commons Net FtpClient
confusingly names the method for setting "transmission mode" .setFileTransferMode
, it frequently leads to the mistakes like you did – People incorrectly try to use FTPClient.setFileTransferMode
to switch between the binary/ascii "data types".
Define transfer mode when trying to SFTP files using Python
pysftp/Paramiko uses an SFTP protocol version 3.
In the SFTP protocol version 3, there are no transfer modes. Or in other words, there is only the binary transfer mode.
Even if pysftp/Paramiko supported a newer version of SFTP, which do support the text/ascii mode, it is unlikely to help you. Most SFTP servers are OpenSSH. And OpenSSH uses SFTP 3 too.
See also How to transfer binary file in SFTP?
If you need to convert the file to Windows format, you need to do it upfront, before a file transfer.
A naive implementation would be like:
WINDOWS_LINE_ENDING = b'\r\n'
UNIX_LINE_ENDING = b'\n'
with open("/local/path/file.txt", "rb") as local_file:
contents = local_file.read()
contents = contents.replace(UNIX_LINE_ENDING, WINDOWS_LINE_ENDING)
with sftp.open("/remote/path/file.txt", "wb") as remote_file:
remote_file.write(contents)
(conversion based on How to convert CRLF to LF on a Windows machine in Python)
Related Topics
Stack Smashing Code Not Working on Linux Kernel 2.6.38.7... Please Help
Omnisharp.Msbuild.Projectmanager Failed to Load Project on Linux
How to Set a Non-Standard Baudrate on a Serial Port Device on Linux
How to Draw 2D Diagram in Linux
How to Split Flv File by Size Using Ffmpeg or Mencoder or Smth Else
Average of Multiple Files Without Considering Missing Values
Will Process Lost Wake-Up Chance in a Preemptive Kernel
Ssh Connection to Ubuntu Open Ssh-Server Requires Login on (Physical) Server via Password First
Bash Assign Output to Variable Inside Here Document
Docker-Compose Stop Working After Docker Desktop Installation on Debian 11
Wc -M in Unix Adds One Character
Libreoffice Command Line Conversion - No Output File
Iterating Over File (And Directory) Names with Bash
Sort Command in Not Working Properly in Unix for Sorting a CSV File
Osx/Linux, Slow Down the Output from Terminal
Command Substitution Doesn't Work in Script Text Passed Over Ssh