Net::FTP does not place errors in $!. This variable is usually reserved for system error messages, not application errors. Consider using the message() and/or code() methods to get the last message returned by the FTP server. (Note: This isn't tested, but since Net::FTP inherits from Net::Cmd, I would expect this would work.)
You're doing a size check after $ftp->get, second-guessing the success/failure response of the get() method. Is there a reason you're doing that? Have you ever had a situation where the file was apparently successfully transferred yet the sizes were different (implying a truncated download)? I'm kind of curious. This check seems redundant to me, but you may have experiences that really do show a problem (perhaps something that should be communicated to the Net::FTP authors). Note that I might anticipate different file sizes if you're transferring a file using ASCII mode between systems with incompatible newline conventions. This shouldn't be considered a failure.