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 - https://sinujohn.github.io/
//
//////////////////////////////////////////////////////////////
#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: https://sinujohn.github.io/
//
//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();
}
}