Sending a file by HTTP POST

Recently I created a program which can send a file to a server in several packets using
HTTP POST. I also created a servlet(in fact, my first servlet!) to receive these file
parts and then create a file using them. Download it.
The program ‘client.c’ sends a file to the server as mentioned in small parts – 100KB, but
you can change the size (set value in SIZELIMIT). The program uses Curl library to
send the file using HTTP POST. Curl is very easy to use. They also have a great tutorial.
The program sends each packet by attaching two additional headers to them – Count and Filename.
‘Count’ is used to set the count of the packet(starts from 1) and ‘Filename’ is the name of the file that is being sent.
File ‘client.c’:
/////////////////////////////////////////////////////////////
//client.c
// Send file to an HTTP server in small parts using POST
// USAGE: client inputfile
//
// Compile:
// gcc -o client client.c -lcurl
//
// Developer:
// Sinu John - sinuvian@gmail.com
// www.sinujohn.wordpress.com
//
//////////////////////////////////////////////////////////////

#include<curl/curl.h>
#include<fcntl.h>
#include<unistd.h>

//No. of bytes to be sent in one pass
#define SIZELIMIT 100*1024

//#define _SEND_DEBUG_

int sendFile(const char *fileName, const char *url)  // Sends file to 'url' with an additional header 'Count' (specifying count of the packet)
{                                                    // An header 'Filename' is also added
  int COUNT=0;
  int fd = open(fileName, O_RDONLY);
  if(fd<0)
  {
    printf("\nERROR: Cannot open the file\n");
    return -1;
  }

  CURL *handle;
  char buf[SIZELIMIT]; //Data to be sent is stored in this buffer. Static Allocation of memory.
  int ndata;
  struct curl_slist *headers=NULL;

  handle = curl_easy_init();

  #ifdef _SEND_DEBUG_
  curl_easy_setopt( handle, CURLOPT_VERBOSE, 1);
  #endif

  curl_easy_setopt( handle, CURLOPT_URL, url);

  while((ndata = read(fd, buf, SIZELIMIT))>0)
  {
    COUNT++;

    #ifdef _SEND_DEBUG_
    printf("\n\n*****************************************************\n");
    printf("@@@@@@ Bytes Read = %d\n", ndata);
    #endif

    ///////////////////////////////////////////////////////
    //////// Setting Count header and Filename header
    char countHeader[20], filenameHeader[50];
    headers=NULL;
    sprintf(countHeader,"Count:%d",COUNT);
    sprintf(filenameHeader,"Filename:%s",fileName);
    headers = curl_slist_append(headers, filenameHeader);
    headers = curl_slist_append(headers, "Expect:");
    headers = curl_slist_append(headers, countHeader);
    curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
    /////////
    ///////////////////////////////////////////////////////B1

    curl_easy_setopt( handle, CURLOPT_POSTFIELDS, buf);
    curl_easy_setopt( handle, CURLOPT_POSTFIELDSIZE, ndata);
    curl_easy_perform( handle );

    ////////////////////////////////////////////////////////
    /////////// Freeing all headers
    curl_slist_free_all(headers);
    ///////////
    ////////////////////////////////////////////////////////B1
  }

  printf("\n\n**** COUNT is %d ****\n\n",COUNT);
  curl_easy_cleanup( handle );
  close(fd);
  return 0;
}

int main(int argc, char **argv)
{
  if(argc<2) { printf("Please provide an input file\n"); return 1; }
  char *fileName = argv[1];
  sendFile(fileName, "http://localhost:8080/postapp/makeapp");
  return 0;
}
The servlet ‘MakeApp.java’, is a very basic program that creates the file at the server from the several
packets. I used Tomcat 6 to deploy it(My first encounter with Tomcat!).
File ‘MakeApp.java’:
///////////////////////////////////////////////////////////////////////
//MakeApp.java
//Servlet for creating a file obtained as several parts
//through various POST requests.
//Creates the file in server folder (in my case: /usr/share/tomcat6/ )
//
//
// Developer: Sinu John - sinuvian@gmail.com
//            sinujohn.wordpress.com
//
//Compile:
//javac -cp /usr/share/tomcat6/lib/tomcat6-servlet-2.5-api-6.0.24.jar MakeApp.java
//
//////////////////////////////////////////////////////////////////////

import java.io.*;

import javax.servlet.http.*;
import javax.servlet.*;

public class MakeApp extends HttpServlet implements SingleThreadModel {
  public void doPost (HttpServletRequest req,
                                         HttpServletResponse res)
        throws ServletException, IOException
  {
	int count;
	String fileName;
	OutputStream fout;
	count=req.getIntHeader("Count");
	fileName = req.getHeader("Filename");
	if(count==1) { fout = new FileOutputStream(fileName); }
	else { fout = new FileOutputStream(fileName, true); }

	InputStream in = req.getInputStream();
	byte buf[] = new byte[req.getContentLength()+1];
	int nbuf;
	do
	{
	  nbuf = in.read(buf, 0, req.getContentLength());
	  if(nbuf>=0)  fout.write(buf, 0, nbuf);
	}while(nbuf>=0);

	fout.close();
        PrintWriter out = res.getWriter();
        out.println("Got file "+fileName+" with Count: "+count);
        out.close();
  }
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s