Uploading file from SD card to remote server?

Here is the code I have so far. It is not documented as well as I would like it, but I can do that later.

The "#define FTPWRITE" determines whether it reads or writes to the FTP server. Commented out, it reads from the FTP server and writes to the SD.

Change your network settings, and the user/password in the doFTP() routine.
Place a file named test.txt in your FTP server.

Upload and open serial monitor. Wait for ready.
Press 'r' and enter to view SD file contents.
Press 'f' and enter to transfer.

#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>

// reads from server and writes to SD file
// uncomment next line to write SD file to server.
// #define FTPWRITE

byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x59, 0x67 };  
IPAddress ip( 192, 168, 0, 2 );    
IPAddress gateway( 192, 168, 0, 1 );
IPAddress subnet( 255, 255, 255, 0 );

// FTP server ip
IPAddress server( 192, 168, 0, 3 );

EthernetClient client;
EthernetClient dclient;

char outBuf[128];
char outCount;

void setup()
{
  Serial.begin(9600);

  if(SD.begin(4) == 0)
  {
    Serial.println("SD init fail");          
  }

  Ethernet.begin(mac, ip, gateway, gateway, subnet); 
  digitalWrite(10,HIGH);
  delay(2000);
  Serial.println("Ready. Press f or r");
}

void loop()
{
  byte inChar;

  inChar = Serial.read();

  if(inChar == 'f')
  {
    if(doFTP()) Serial.println("FTP OK");
    else Serial.println("FTP FAIL");
  }

  if(inChar == 'r')
  {
    readSD();    
  }

}

File fh;

byte doFTP()
{
#ifdef FTPWRITE
  fh = SD.open("test.txt",FILE_READ);
#else
  SD.remove("test.txt");
  fh = SD.open("test.txt",FILE_WRITE);
#endif

  if(!fh)
  {
    Serial.println("SD open fail");
    return 0;    
  }

  Serial.println("SD opened");
  
  if (client.connect(server,21)) {
    Serial.println("Command connected");
  } 
  else {
    Serial.println("Command connection failed");
    fh.close();
    return 0;
  }

  if(!eRcv()) return 0;

// change to your user
  client.write("USER myusername\r\n");

  if(!eRcv()) return 0;

// change to your password  
  client.write("PASS mypassword\r\n");

  if(!eRcv()) return 0;

  client.write("SYST\r\n");

  if(!eRcv()) return 0;

  client.write("PASV\r\n");

  if(!eRcv()) return 0;

// new code

  char *tStr = strtok(outBuf,"(,");
  int array_pasv[6];
  for ( int i = 0; i < 6; i++) {
    tStr = strtok(NULL,"(,");
    array_pasv[i] = atoi(tStr);
    if(tStr == NULL)
    {
      Serial.println("Bad PASV Answer");    
      client.stop();
      fh.close(); 
      return 0;  
    }
  }

  unsigned int hiPort,loPort;

  hiPort = array_pasv[4] << 8;
  loPort = array_pasv[5] & 255;

// end of new code

  Serial.print("Data port: ");
  hiPort = hiPort | loPort;
  Serial.println(hiPort);
  
  if (dclient.connect(server,hiPort)) {
    Serial.println("Data connected");
  } 
  else {
    Serial.println("Data connection failed");
    client.stop();
    fh.close();
    return 0;
  }

#ifdef FTPWRITE 
  client.write("STOR /test.txt\r\n");
#else
  client.write("RETR /test.txt\r\n");
#endif

  if(!eRcv())
  {
    dclient.stop();
    return 0;
  }

#ifdef FTPWRITE
  Serial.println("Writing");

// This needs improvement

  while(fh.available())
  {
    char c = fh.read();
    dclient.write(c);
  }

#else
  while(dclient.connected())
  {
    while(dclient.available())
    {
      char c = dclient.read();
      fh.write(c);      
      Serial.write(c); 
    }
  }
#endif

  dclient.stop();
  Serial.println("Data disconnected");
  
  if(!eRcv()) return 0;

  client.write("QUIT\r\n");

  if(!eRcv()) return 0;

  client.stop();
  Serial.println("Command disconnected");

  fh.close();
  Serial.println("SD closed");
  return 1;
}

byte eRcv()
{
  byte respCode;
  byte thisByte;

  while(!client.available()) delay(1);

  respCode = client.peek();

  outCount = 0;
  
  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);

    if(outCount < 127)
    {
      outBuf[outCount] = thisByte;
      outCount++;      
      outBuf[outCount] = 0;
    }
  }

  if(respCode >= '4')
  {
    efail();
    return 0;  
  }

  return 1;
}


void efail()
{
  byte thisByte = 0;

  client.write("QUIT\r\n");

  while(!client.available()) delay(1);

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }

  client.stop();
  Serial.println("Command disconnected");
  fh.close();
  Serial.println("SD closed");
}

void readSD()
{
  fh = SD.open("test.txt",FILE_READ);

  if(!fh)
  {
    Serial.println("SD open fail");
    return;    
  }

  while(fh.available())
  {
    Serial.write(fh.read());
  }
  
  fh.close();
}

If you have questions, ask. My apology in advance for any typos.

edit: This is FTP client code. I could not find a way to use passive mode with the Arduino as the server.

edit2: Code change on passive mode port retrieval, thanks to cedric2. :slight_smile:
That saves about 2K of memory.