Search code examples
pythonftpjythonftplib

Downloading file with a space in filename using ftplib


I'm downloading two files from a C-More industrial HMI FTP server. I don't know what OS the HMI is running but I suspect that its FTP server has some quirks. Using Jython 2.7, one file can be read without difficulty but the other has a space in the file name and the normal wrap-in-quotes solution doesn't work - yet.

The following works in the Windows 10 FTP client.

ftp> get NO_SPACES.csv
200 PORT command successful.
150 Opening ASCII mode data connection for NO_SPACES.csv.
226 Transfer complete.
ftp: 12774 bytes received in 0.27Seconds 47.66Kbytes/sec.

ftp> get "WITH SPACE.csv"
200 PORT command successful.
150 Opening ASCII mode data connection for WITH SPACE.csv.
226 Transfer complete.
ftp: 6328 bytes received in 0.02Seconds 316.40Kbytes/sec.

So far, so good. Now try it in Python:

ftp = FTP(myIP)                         # Connect.
ftp.login(userName, password)           # Login.
ftp.set_pasv(False)                     # Required by the C-More panel for some reason.
with io.BytesIO() as binary_buffer:
    # read all of products into a binary buffer
#   ftp.retrbinary("RETR NO_SPACES.csv", binary_buffer.write)       # This line works.
    ftp.retrbinary('RETR "WITH SPACE.csv"', binary_buffer.write)    # This one doesn't.

The script console in my development system reports:

ftplib.error_perm: 550 "WITH SPACE.csv": Requested action not taken.

  1. Filenames have been changed to protect the innocent.
  2. Windows FTP likes the get command. Python seems to favour RETR.
  3. I've tried 'RETR "WITH SPACE.csv"' and "RETR 'WITH SPACE.csv'". Same result.
  4. If I have to I can rename the files in the HMI but that will require some validation and paperwork and that's no fun.
  5. I'm developing this on the latest version of Inductive Automation's Ignition! SCADA system which uses Jython 2.7.

Has anyone got any ideas for me to try?


Solution

  • The ftplib has no issue with spaces. The problem are the quotes you add to the RETR command. There should be no quotes:

    ftp.retrbinary('RETR WITH SPACE.csv', binary_buffer.write)
    

    If you enable the debug mode in ftp using the -d switch, you will see that it also sends no quotes to the FTP server in the RETR command:

    ftp> get "WITH SPACE.csv"
    ---> PORT 127,0,0,1,15,145
    200 Port command successful
    ---> RETR WITH SPACE.csv
    150 Opening data channel for file download from server of "/WITH SPACE.csv"
    226 Successfully transferred "/WITH SPACE.csv"
    ftp: 12 bytes received in 0.00Seconds 12000.00Kbytes/sec.
    

    Note that the get is a commandline ftp client user command that translates to the FTP protocol RETR command.