rebol [ Title: "Demo FTP upload chunks" File: %demo-ftp-upload-chunks.r Date: 21-Aug-2006 Version: 1.0.1 Progress: 0.45 Status: "working, lightly tested" Needs: [] Author: "Anton Rolls" Language: "English" Purpose: {Upload a file to an FTP server in direct mode, a chunk at a time (so the whole source file is not buffered in memory).} Usage: {} History: [ 1.0.0 [2-Jun-2006 {First version adapted from Oldes' example on AltME} "Anton"] 1.0.1 [21-Aug-2006 {adapted further for testing and more comments for clarity, tested text and binary modes} "Anton"] ] ToDo: { - test with a large file - test with patch/ftp-open-new-patch.r } Notes: { Using text mode I noticed a difference between the total-size of the source-file and the total number of bytes actually transferred. The reason is because on Windows the source-file contains CRLF line-terminators. When rebol does COPY (and the port was opened in text mode), it translates those two-character line terminators to a single character, which, if you examine the buffer, can be seen as "^/". Since two characters are being converted to one, this shrinks the file by one byte for every newline it contains. That obviously makes estimating the destination file size difficult, and, in this script, my transferred percentage will be a little inaccurate. You will notice shrinkage when transferring from Windows -> Linux/Mac, and expansion when transferring from Linux/Mac -> Windows. You can avoid this problem completely by specifying binary mode, eg: source-port: open/binary/direct/read source-file target-port: open/binary/direct/new/write target-spec The files will now be transferred exactly, without any modification, and the progress should also be accurate. } ] source-file: %ftp-upload-chunks.r ; You can do this: ;target-spec: [scheme: 'ftp host: "ftp.host.com" user: "username" pass: "password") path: "rebol/demo/" target: "ftp-upload-chunks.r"] ; But I do this, to keep my connection details out of my public scripts: target-spec: do view-root/../ftp-access-spec.r ; returns a block as above repend select target-spec [path:] "rebol/demo/" change clear select target-spec [target:] "ftp-upload-chunks.r" ;source-port: open/direct/read source-file ; TEXT mode source-port: open/binary/direct/read source-file ; BINARY mode ; It's a file, so we can get the total size with: total-size: source-port/size ;target-port: open/direct/new/write target-spec ; TEXT mode target-port: open/binary/direct/new/write target-spec ; BINARY mode transferred: 0 ; <-- keeps track of bytes transferred while [buffer: copy/part source-port 1000][ ; get a chunk of 1000 bytes from the source file insert target-port buffer ; Show progress transferred: transferred + length? buffer print ["transferred" transferred "bytes of" total-size "total =" to-integer 100 * transferred / total-size "%"] ] close target-port close source-port ; verify it worked: probe info? http://anton.wildit.net.au/rebol/demo/ftp-upload-chunks.r