NOTE: A link to the companion source code for FTPSNDFILE is featured
near the bottom of the article.
A few years back I wrote yet another popular CL command, FTPSNDFILE. This
command simplifies FTP transfers between AS/400 systems. It was so popular
with my readers and AS/400 developers that it is one of a growing package of
tools that I've created that seem to be in just about every shop.
Basically, FTPSNDFILE allows you to transfer via FTP an AS/400 database
file to another system. That other system does not need to be an AS/400,
however. Sending the Customer Master file to another system in your own
network is simply a matter of calling FTPSNDFILE like this:
FTPSNDFILE RMTSYS('192.168.1.123') FILE(ARLIB/CUSTMAST) USER(MYUSERID) PWD(ROSEBUD)
For the last 7 years this command has been widely used and has "just
worked". Recently however, I received a small number of requests to enhance
FTPSNDFILE. This specifically focused on a request I received when I first
published the command, but then heard nothing further. That request was to
support the transfer of SAVF (save file) objects in addition to database
files. Coincidentally, I also had a client who needed this capability so I
decided to implement it.
Initially I thought it would take a lot of work and that I should create
a separate command, perhaps FTPSNDSAVF, that would transfer only save file
objects. I began looking at the old code and realized it was already doing
most of what I needed it to do. So I worked a little magic, changed a few
lines of code, and it worked the first time.
DropBox.com gives you a "sky drive"
in the cloud that automatically syncs between your PCs, Mac, iPhone, Android,
and just about everything (except IBM i).
You can
sign up for a free 2GB dropbox account here
(that's what I use) . Purchase more space only when and if its needed. I've been using it for over a year and
have had no issues. I highly recommend it. - Bob Cozzi
FTPSNDFILE - Source Code
The FTPSNDFILE command definition source code is listed below. It
contains over a dozen parameter definitions and may be prompted both in a
CLP program during SEU or RDp and from Command Entry.
FTPSNDFILE: CMD PROMPT('Send File Using FTP')
/**********************************************/
/* Command processing program is FTPSNDFILE */
/**********************************************/
/* (c) 2005 - 2011 by Robert Cozzi, Jr. */
/*--------------------------------------------*/
/* REQUIREMENTS: FTP server must be active. */
/* The FTP source file for */
/* the generated FTP script */
/* must exist, but the member */
/* is automaticallyed added. */
/* The LOG file must exist */
/* and should be 79 or 80 */
/* bytes in length--a typical */
/* source file is acceptable. */
/**********************************************/
IP: PARM KWD(RMTSYS) TYPE(*CHAR) LEN(128) MIN(1) +
EXPR(*YES) PROMPT('Remote IP or FTP server')
FROMFILE: PARM KWD(FILE) TYPE(QUAL1) MIN(1) PROMPT('Local +
file')
PARM KWD(MBR) TYPE(*GENERIC) LEN(10) DFT(*FIRST) +
SPCVAL((*FILE) (*FIRST) (*LAST) (*ALL)) +
EXPR(*YES) PROMPT('Local member')
QUAL1: QUAL TYPE(*NAME) LEN(10) MIN(1) EXPR(*YES)
QUAL TYPE(*NAME) DFT(*LIBL) SPCVAL((*LIBL)) +
EXPR(*YES) PROMPT('Library')
TOFILE: PARM KWD(TOFILE) TYPE(QUAL2) PROMPT('Remote file')
TOMBR: PARM KWD(TOMBR) TYPE(*NAME) LEN(10) DFT(*FROMMBR) +
SPCVAL((*FROMMBR) (*TOFILE)) EXPR(*YES) +
PROMPT('Remote member')
QUAL2: QUAL TYPE(*NAME) LEN(10) DFT(*FROMFILE) +
SPCVAL((*FROMFILE)) EXPR(*YES)
QUAL TYPE(*NAME) DFT(*FROMLIB) SPCVAL((*FROMLIB)) +
EXPR(*YES) PROMPT('Library')
REPLACE: PARM KWD(REPLACE) TYPE(*LGL) LEN(1) RSTD(*YES) +
DFT(*YES) SPCVAL((*YES '1') (*NO '0')) +
EXPR(*YES) PROMPT('Replace data on remote +
system')
USER: PARM KWD(USER) TYPE(*CHAR) LEN(64) DFT(*CURRENT) +
SPCVAL((*CURRENT)) EXPR(*YES) +
PROMPT('Remote FTP User ID')
PWD: PARM KWD(PWD) TYPE(*CHAR) LEN(64) DFT(*USERID) +
EXPR(*YES) DSPINPUT(*PROMPT) +
PROMPT('Remote FTP Password')
MODE: PARM KWD(MODE) TYPE(*CHAR) LEN(10) RSTD(*YES) +
DFT(*BINARY) SPCVAL((*BINARY BINARY) +
(*TEXT ASCII) (BINARY) (ASCII) (TEXT +
ASCII)) EXPR(*YES) PROMPT('Transfer mode')
SRCFILE: PARM KWD(SRCFILE) TYPE(QUAL3) PROMPT('Src file +
to receive FTP script')
PARM KWD(SRCMBR) TYPE(*NAME) LEN(10) +
DFT(*FROMMBR) SPCVAL((*FROMMBR) (*GEN)) +
EXPR(*YES) PROMPT('Script source member')
QUAL3: QUAL TYPE(*NAME) LEN(10) DFT(QFTPSRC) EXPR(*YES)
QUAL TYPE(*NAME) DFT(QTEMP) SPCVAL((*LIBL)) +
EXPR(*YES) PROMPT('Library')
/*************************************************************/
/** The LOG member can be a source or database file. */
/** A record length of 79 or 80 or more than 80 is needed. */
/** If the log file does not exist, it is created for you. */
/*************************************************************/
LOG: PARM KWD(LOG) TYPE(QUAL4) DFT(*STDOUT) +
SNGVAL((*STDOUT) (*STDIO *STDOUT) +
(*SRCFILE) (*NONE)) PROMPT('FTP log file')
PARM KWD(LOGMBR) TYPE(*NAME) LEN(10) +
DFT(*FROMMBR) SPCVAL((*FROMMBR) (*SRCMBR +
*SCRIPT) (*SCRIPT)) EXPR(*YES) +
PROMPT('Log member')
QUAL4: QUAL TYPE(*NAME) LEN(10) SPCVAL((QFTPLOG)) +
EXPR(*YES)
QUAL TYPE(*NAME) DFT(QTEMP) SPCVAL((*LIBL)) +
EXPR(*YES) PROMPT('Library')
/* The follow parmaeter is ignored when LOG(*STDIO) is specified. */
DSPFTPLOG: PARM KWD(DSPLOG) TYPE(*LGL) RSTD(*YES) DFT(*YES) +
SPCVAL((*YES '1') (*NO '0')) EXPR(*YES) +
PROMPT('Display FTP transfer log')
When sending between AS/400's the RMTSYS, FILE and USER/PWD parameters
are really all that's needed. The only time you would need to include, for
example, the TOFILE parameter is when the file name on the target system
should be different from the name on the originating system.
FTPSNDFILE defaults to the FTP transfer mode of BINARY. Normally you
would never need to change this when sending between AS/400's. If sending a
source file to a PC platform, then you may want to use the ASCII option for
the MODE parameter.
FTP Script and Log
FTPSNDFILE generates a source file member to perform the FTP. This is
called an "FTP Script". I use QFTPSRC as the source file name, and add a
source member name that receives the script named the same as the member
name of the file being transferred. The default QFTPSRC file's library is
QTEMP. This means that FTPSNDFILE creates the source file at runtime, adds
the source member, and then writes the generated FTP script out to that
member. If you want to preserve the script you may want to create a QFTPSRC
source file in your own library. Please use a record length of 112,
RCDLEN(112) for all new source files you create.
FTP Isn't MOVOBJ
Unlike the safety net of IBM i CL commands, FTP originated on a non-i
platform, so it isn't as safe to use as, for example. the MOVOBJ command.
There are few checks and definitely no "Are you sure?" prompts. So while
there is a REPLACE keyword parameter on the FTPSNDFILE, its purpose is to
include the (Replace clause on the PUT command. It does NOT insure that
specifying REPLACE(*NO) will avoid replacing the target object. For example,
when you send a save file to another AS/400, the target save file is
replaced with the contents of the new save file regardless of the REPLACE
parameter.
So make sure you are doing what you intend to do before using any non-IBM
i interface, such as FTP.
FTPSNDFILE New Use -- SAVE FILES!
In a previous issue of RPG Report, I wrote about D/R (disaster recovery)
and a recent experience I had with a client of mine. The feedback I received
was 99% positive, and I thank you for that. I did, however, receive one
comment that basically said:
"Bob, I've been reading your technical stuff for
years, but this non-technical article on D/R bored me."
I do understand that people want continuous technical content that they
can "take home and use immediately". That has sort of become a theme of mine
over the last 28 years of writing this kind of material. Yes, I started
writing in 1983.
So I've come up with a use for the FTPSNDFILE command (which is
technical) that applies to the boring article I wrote last time on
Disaster/Recovery. This use advocates saving your data and other objects to
a traditional savefile, and then using FTPSNDFILE to copy those savefiles to
a remote location.
I've added a Job Scheduler Entry that automatically backs up today's work
to a save file and then using FTPSNDFILE and its new SAVF support, I send it
to a remote AS/400 (in another country) for backup purposes. I even wrap it
all in a CL program that retrieves the JOB DATE and uses that as the
savefile name so that I get a fresh copy every time it is run, along with an
archive of prior backups, just in case.
Yes I know that will fill up the remote system with backups, but I also
know how to use the WRKOBJ command, and type in option 4 on the unwanted
savefile archives.
FTPSNDFILE Source Code
Premium MidrangeNews.com members can download a ZIP file containing the
FTPSNDFILE CMD and RPG IV source code. Simply transfer it up to a source
file on your AS/400 using RDp or FTP and compile them with PDM option 14 or
the right-click thing in RDp.
Download FTPSNDFILE.ZIP here
Make sure your FTP server is started, to do that use the STRTCPSVR *FTP
command.
Then go ahead and transfer a file to another AS/400 using
FTPSNDFILE. Be sure to prompt it (F4) so you specify all the parameters
you need.
You're Welcome!
Call Me
Bob Cozzi is available
for consulting or on-site training in RPG IV, SQL, and CGI/Web as
well as perform contract programming. Currently many shops are asking Cozzi to join them for 1
to 3 days of Q&A and consulting with their RPG staff. The Staff gets to ask real-world
questions that apply to their unique situations. Contact Cozzi by sending him an
email at: bob at rpgworld.com
Look for Bob in the upcoming STARZ network TV production of "BOSS" a
continuing TV series staring Kelsey Grammer of "Frasier" and "Cheers".
Coming this fall only on the STARZ network. (First NASA, then CNN, now
STARZ, what'll Cozzi do next?)
Bob also accepts your questions for use in future RPG Report
articles or content for midrangeNews.com. Topics of interest include: RPG IV,
Web development with RPG IV, APIs, C/C++ or anything else IBM i development related (except subfiles,
data areas and RPGII/III because Bob doesn't care about that stuff) write
your questions
using the Feedback link
on the midrangeNews.com website.
You can subscribe to RPG Report (we call it "follow") by
visiting the RPG Report
page
on midrangeNews.com and then click the FOLLOW link in the table of contents
for that
page. To unsubscribe, simply click that same link. You must be
signed up and signed
in to midrangeNews.com to start following RPG Report.
Follow Bob Cozzi on Twitter