Mats

Mats

FTP with Erlang FTP client

Hi,
I’ve seen a couple of examples using the Erlang FTP client from Elixir and I have succesfully stepped through an example but now I’m stuck.
I keep getting an {:error, :epath} error although the file is there.

ftp_target_directory = ftp_target_directory |> String.to_charlist
ftp_host = Config.get(:importer, :ftp_host) |> String.to_charlist
ftp_user = Config.get(:importer, :ftp_user) |> String.to_charlist
ftp_pass = Config.get(:importer, :ftp_pass) |> String.to_charlist

Logger.info("Downloading files from #{inspect ftp_host} to #{inspect ftp_target_directory}")

:application.start :inets 
{:ok, pid} = :inets.start(:ftpc, host: ftp_host)
:ftp.user(pid, ftp_user, ftp_pass)
:ftp.pwd(pid)
:ftp.lcd(pid, ftp_target_directory)
:ftp.type(pid, :binary)
directory_list = get_listing(pid)
Enum.each(directory_list, fn directory ->
    :ftp.cd(pid, directory)
    files = get_listing(pid)
    Enum.each(files, fn file ->
      Logger.info("Downloading #{inspect file}")
      status = :ftp.recv(pid, file)
      Logger.info("Status #{inspect status}")
    end) 
    :ftp.cd(pid, '..')
end)
end

defp get_listing(pid) do
   {:ok, listing} = :ftp.nlist(pid)
   listing = listing |> String.Chars.List.to_string |> String.split("\r\n", trim: true)
   Enum.map(listing, fn item -> String.to_char_list(item) end)
end

I’ve put the client in verbose mode but I can’t see the client actually requesting the file, all I get is the error above.
I’m using the bitwalker/alpine-erlang:6.1 with elixir 1.4.

iex(testdownload@127.0.0.1)6> {:ok, pid} = :inets.start(:ftpc, host: ftp_host, verbose: true)
\n220 Welcome to the FTP Service."er (v. 7.2.0)
{:ok, pid<0.647.0>}
iex(testdownload@127.0.0.1)7> :ftp.user(pid, ftp_user, ftp_pass)
“Sending: USER secret”
“Receiving: 331 Password required for secret”
“Sending: PASS secretpass”
“Receiving: 230 Logon OK. Proceed.”
:ok
iex(testdownload@127.0.0.1)8> :ftp.pwd(pid)
“Sending: PWD”
“Receiving: 257 "/" is current directory.”
{:ok, ‘/’}
iex(testdownload@127.0.0.1)9> :ftp.lcd(pid, ftp_target_directory)
:ok
iex(testdownload@127.0.0.1)10> :ftp.type(pid, :binary)
“Sending: TYPE I”
“Receiving: 200 Type set to I”
:ok
iex(testdownload@127.0.0.1)11> :ftp.cd(pid, ‘files’)
“Sending: CWD files”
“Receiving: 250 CWD command successful.”
:ok
iex(testdownload@127.0.0.1)14> :ftp.nlist(pid)
“Sending: PASV”
“Receiving: 227 Entering Passive Mode (147,14,4,15,156,195)”
“Sending: NLST”
“Receiving: 150 Opening data connection for file list.”
“Receiving: 226 Transfer complete.”
{:ok, ‘file.csv\r\n’}
iex(testdownload@127.0.0.1)12> :ftp.recv(pid, ‘file.csv’)
{:error, :epath}

Can anyone tell me what I’m doing wrong? :slight_smile:

First Post!

NobbZ

NobbZ

The error you get is described as foolows:

epath
No such file or directory, or directory already exists, or permission denied.

So have you checked with another FTP client if you can download the file using that one? Also put it in verbose and check if it uses relative path to current dir or full path for RECV, change your code accordingly then.

Most Liked

NobbZ

NobbZ

Please try to use :ftp.recv/3 and provide a path and filename that you are definitevely allowed to write. I’m not quite sure where BEAM will try to create the file if the third parameter is missing.

Mats

Mats

Just a quick follow up. It was indeed file system rights that were my problem.
I was building the release with a docker mix plugin that used the USER directive in the Dockerfile.
Everything works as expected now.

Thanks for your help!

jnmandal

jnmandal

According to the erlang docs, :epath means: “No such file or directory, or directory already exists, or permission denied.”

The error codes are listed at the bottom of this page: ftp

Where Next?

Popular in Questions Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

Other popular topics Top

JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement