[Haskell-cafe] upload file with ftp

Kees Bleijenberg K.Bleijenberg at lijbrandt.nl
Tue Jan 5 15:54:56 UTC 2021

Hi Brandon,


The ftp-client I use (total commander) does not use passive mode.  I changed the host to another server. And now I do not get an exception, no error messages, but nothing is uploaded.


Unfortunately is ‘working in passive mode’ not so easy (at least not to me). After login I send the ‘pasv’ command and I get back a IP address and a port (I assume). Do I have to create a new connection with a handle to this new port for the stor command?  I don’t know how to do that in network.ftp.client. A hint or better a working example would be nice.



Van: Brandon Allbery [mailto:allbery.b at gmail.com] 
Verzonden: dinsdag 5 januari 2021 13:49
Aan: Kees Bleijenberg <K.Bleijenberg at lijbrandt.nl>
CC: haskell-cafe <haskell-cafe at haskell.org>
Onderwerp: Re: [Haskell-cafe] FW: upload file with ftp


At a guess, you're using a modern FTP client that defaults to passive mode for compatibility with firewalls, and you'll need to check the docs to see how to do passive mode with Network.Client.FTP.


On Tue, Jan 5, 2021 at 7:24 AM Kees Bleijenberg <K.Bleijenberg at lijbrandt.nl <mailto:K.Bleijenberg at lijbrandt.nl> > wrote:

I want to upload a file with ftp using library Network.FTP.Client.
The OS is Windows 64 and ghc version is 8.6.4.

This is the code:

import System.FilePath.Windows
import Network.FTP.Client
import qualified Data.ByteString as B
testFtp :: IO (Either String ())
testFtp = do
   let host = "copecco"  -- this is from my hosts file       
       username = ****
       pwd = ****
       ftpDir = "registratie"
       fileToSend = "globals.pas"  -- a test text file
   putStrLn $ "Connect to " ++ host
   withFTP host 21 $ \h ftpResponse -> do 
         print ftpResponse
         if frStatus ftpResponse == Success 
         then do 
                  putStrLn "Connected"
                  loginResp <- login h username pwd
                  print loginResp
                  if frStatus loginResp == Success
                  then do 
                           putStrLn $ "Change directory to " ++ ftpDir
                           cwdResp <- cwd h ftpDir
                           print cwdResp
                           if frStatus cwdResp == Success 
                           then do  
                                    putStrLn "Read file from disk"
                                    let ftpFn =  takeFileName fileToSend 
                                    fileContents <- B.readFile fileToSend 
                                    putStrLn $ "File size: " ++ show
(B.length fileContents) ++ " bytes"
                                    stor h ftpFn fileContents TI
                                    return $ Right ()
                           else return $ Left $ "Ftp error cwd. Code: " ++
show (frCode ftpResponse)
                  else return $ Left $ "Ftp error login. Code: " ++ show
(frCode ftpResponse)
         else return $ Left $ "Connect to host " ++ host  ++ " failed. Code:
" ++ show (frCode ftpResponse)

This is the response:
Connect to copecco

220 (vsFTPd 3.0.2)


230 Login successful.

Change directory to registratie

250 Directory successfully changed.

Read file

File size: 27015 bytes

*** Exception: Network.Socket.connect: <socket: 444>: failed (Connection
timed out (WSAETIMEDOUT))  

Everything works fine until the stor commmand. 
When I upload the same file with another ftp client program everything works
(no permission problems).

What is wrong and how do I get the result codes for the stor command?


Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
Only members subscribed via the mailman list are allowed to post.



brandon s allbery kf8nh

allbery.b at gmail.com <mailto:allbery.b at gmail.com> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20210105/eea7e6d7/attachment.html>

More information about the Haskell-Cafe mailing list