2

I need to manually interrupt am FTP upload and then test that I can resume the upload. I am using Python's ftplib module. I have tried below code:

# Consider I have logged in using valid ftp user
# File is of 20 MB
counter = 0
file_name = 'test.dat'
ftp_dir = 'test_ftp_dir'

with open(file_address, 'rb') as file:
    ftp.set_debuglevel(2)
    ftp.cwd(ftp_dir)
    ftp.voidcmd('TYPE I')
    with ftp.transfercmd(f'STOR {file_name}', None) as conn:
        while True:
            # Read 1 MB
            buf = file.read(1000000)
            if not buf:
                break
            conn.sendall(buf)
            counter += 1
            if counter == 5:
                # Stop after 5 MB
                LOG.info("STEP-3: Abort client transfer")
                break

# Reading file again and logging again using the ftp user
with open(file_address, 'rb') as file:
    ftp.set_debuglevel(2)
    ftp.cwd(ftp_dir)
    ftp.voidcmd('TYPE I')
    ftp.storbinary(f'STOR {file_name}', file, rest=ftp.size(file_name))

Instead of restarting the upload from 5 MB, It is sending the full file while appending to the original one. Say I have sent 5 MB of a file then I can see the file of 5 MB and when I try to resume it, it sends the whole 20 MB file making it a total 25 MB file. Please help me on this. Thanks.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Luffy
  • 83
  • 1
  • 10

1 Answers1

2

You have to seek the source local file to the restart position before initiating the transfer:

# Reading file again and logging again using the ftp user
with open(file_address, 'rb') as file:
    rest = ftp.size(file_name)
    file.seek(rest)
    ftp.cwd(ftp_dir)
    ftp.storbinary(f'STOR {file_name}', file, rest=rest)

The ftplib won't seek the file for you, that would limit its use. There are scenarios, where you would not want it to seek. And there are file-like objects that do not support seeking.


For a full code of a resumable FTP upload, see:
Handling disconnects in Python ftplib FTP transfers file upload

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992