Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Sending a file to HTTP server via a multi-part flat form

Status
Not open for further replies.

tewari68

Programmer
Jan 25, 2005
87
0
0
US
Hi,
I need to send a flat file to http server. The file that needs to be sent is an xml file which is created by another routine. FTP is not an option, I have to send it to an http server via a multi-part form.
so far I have this code
Code:
int Send_to_DB_via_HTTP(string filename)
{
 	int sock;                          /*  Socket descriptor */
    	struct sockaddr_in echoServAddr;   /*  server address */
    	unsigned short echoServPort;       /*  server port */
    	char *servIP;                      /*  Server IP address (dotted quad) */
	char *url;
    	char *echoString;                  /*  String to send to echo server */
    	char echoBuffer[RCVBUFSIZE];       /* Buffer for echo string */
    	unsigned int echoStringLen;        /* Length of string to echo */
    	int bytesRcvd, totalBytesRcvd;     /* Bytes read in single recv()
                                           and total bytes read */
	int                         first_form_len=0;
    	int                         second_form_len=0;
	unsigned 		    count = 0;
	char* Traveller_output_buffer;
	FILE * pFile;
	long lSize;
	size_t result;
	char* buf;
	pFile = fopen ( filename.c_str(), "rb" );
	// obtain file size:
  	fseek (pFile , 0 , SEEK_END);
  	lSize = ftell (pFile);
  	rewind (pFile);
	// allocate memory to contain the whole file:
  	Traveller_output_buffer = (char*) malloc (sizeof(char)*lSize);
  	if (Traveller_output_buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
	
  	// copy the file into the buffer:
  	result = fread (Traveller_output_buffer,1,lSize,pFile);

	//ifstream file_to_send;
	
	unsigned data_len;
	servIP = "192.168.2.20";
	echoServPort = 80;
	url = "[URL unfurl="true"]http://something.dyndns.org";[/URL]
	data_len = sizeof(char)*lSize;
	/* Create a reliable, stream socket using TCP */
	if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
     	 cout << " socket () failed" << endl;
	/* Construct the server address structure */
	memset(&echoServAddr, 0, sizeof(echoServAddr));         /* Zero out structure */
	echoServAddr.sin_family         = AF_INET;              /* Internet address family */
	echoServAddr.sin_addr.s_addr = inet_addr(servlP);       /* Server IP address */
	echoServAddr.sin_port           = htons(echoServPort); /* Server port */
	/* Establish the connection to the echo server */
	if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
     	 cout<< "Error Connecting to " << servIP << endl;
	else
	 cout << "Connection Successfull to " << servIP << endl;

	first_form_len += snprintf(
                        &buffer1[first_form_len],
                        sizeof(buffer1) - first_form_len,
                        "Content-Disposition: form-data; name=\"flat_file\"; filename=\"new.dat\"\r\n" );
	
	first_form_len += snprintf(
                        &buffer1[first_form_len],
                        sizeof(buffer1) - first_form_len,
                        "Content-Type: text/plain\r\n\r\n" );
	cout << first_form_len << endl;
	//Start the form off with the boundary string
    	second_form_len += snprintf(
                        &buffer1[first_form_len+second_form_len],
                        sizeof(buffer1) - (first_form_len+second_form_len),
                        "%s%s\r\n",
                        "--",BOUNDARY_STRING );
	second_form_len += snprintf(
                        &buffer1[(first_form_len+second_form_len)],
                        sizeof(buffer1) - (first_form_len+second_form_len),
                        "Content-Disposition: form-data; name=\"filename\"\r\n\r\n%s_auto_end\r\n",
						syssn_no );
	//End of multi-part form
    	second_form_len += snprintf(
                        &buffer1[(first_form_len+second_form_len)],
                        sizeof(buffer1) - (first_form_len+second_form_len),
                        "%s%s%s\r\n",
                        "--",BOUNDARY_STRING,"--" );

	// Put together the headers for HTTP POST
    	count = snprintf(
                       &buffer[0],
                       sizeof(buffer),
                       "POST %s HTTP/1.0\r\n",
                       url );
    	count += snprintf(
                        &buffer[count],
                        sizeof(buffer) - count,
                        "Accept-Language: en-us\r\n" );
    	count += snprintf(
                        &buffer[count],
                        sizeof(buffer) - count,
                        "Content-Type: multipart/form-data; boundary=%s\r\n",
                        BOUNDARY_STRING);

    
    	count += snprintf(
                        &buffer[count],
                        sizeof(buffer) - count,
                        "User-Agent: Mozilla/3.01 (compatible;  %s-%s/%d.%d.%02d r%d)\r\n");
    	count += snprintf(
                        &buffer[count],
                        sizeof(buffer) - count,
                        "Host: %s\r\n",
                        servIP);


    	count += snprintf(
                        &buffer[count],
                        sizeof(buffer) - count,
                        "Pragma: no-cache\r\n" );
    	count += snprintf(
                        &buffer[count],
                        sizeof(buffer) - count,
                        "Content-Length: %d\r\n",
                        data_len+first_form_len+second_form_len );
    	count += snprintf(
                        &buffer[count],
                        sizeof(buffer) - count,
                        "\r\n" );
	cout << buffer1 << endl;
	string status;


	//Send the "POST" header to the HTTP server.
	if (send(sock, buffer, count, 0) == -1) {
		
		//status = perror("send");
		cout << "Stats Worker: received socket error %d on header send\n" << endl;
		return -1;
	}
	else
	{
		cout << "data Sent" << endl;
	}
	

	//Send the first part of the form data to the HTTP server.
	if (send(sock, buffer1, first_form_len, 0) == -1) {
		
		//status = CK_Get_last_error();
		cout << "Stats Worker: received socket error %d on header send\n" << endl;
		return -1;
	}

    //Now send the flat file
    if (send(sock, Traveller_output_buffer, data_len, 0) == -1) {
		
		//status = CK_Get_last_error();
	
		cout << "Stats Worker: received socket error %d on message send\n" << endl;
		return -1;
	}


	//Send the last part of the form data to the HTTP server.
	if (send(sock, buffer1+first_form_len, second_form_len, 0) == -1) {
		
		//status = CK_Get_last_error();
		cout << "Stats Worker: received socket error %d on header send\n" << endl;
		return -1;
	}
	else
	{
		cout << "Data has been Sent Successfully" << endl;
	}
	int n = recv(sock, buf, sizeof(buf), 0);
        while (n > 0) {
            printf(buf);
            n = recv(sock, buf, sizeof(buf), 0);
        }
	

close(sock);
}
from the server I get the following response however the file is not uploaded. \
Code:
HTTP/1.1 200 OK
Date: Sat, 06 Sep 2008 17:34:48 GMT
Server: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch10
X-Powered-By: PHP/5.2.0-8+etch10
Content-Length: 28
Connection: close
Content-Type: text/html; charset=UTF-8
Do I need to have some server side script too to grab all the data sent and write it to a file?
Really appreciate any help.
Thanks
Appreciate any help in this regards.
 
Hi,
Calling all experts. Can someone help me out on this one.
Or is it something not done by anybody earlier and not doable ????????

Thanks
 
Use this to watch the network, and compare what your program does with that of a known working program such as a web browser doing the same thing.

> if (send(sock, buffer1, first_form_len, 0) == -1)
What about all the other status results ?
returning 0 is special
returning 1, 2, 3, 4, ... first_form_len-2, first_form_len-1, first_form_len all indicate varying degress of success. Anything less than first_form_len means you need to go round again and send the remaining (first_form_len-result) bytes.

Both send() and recv() MAY result in less bytes than you asked for being transferred. It's up to you to catch this and try again with the remainder.


--
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
 
Hi Salem,
The file upload part works perfectly, I had to write a server side cgi to get all the content and write it to a file.
The file upload works fine, however I have some other issues, i.e. if I try to send more fields in theh mulitpart form-data post request I keep getting this error


Server Response is
HTTP/1.1 200 OK
Date: Fri, 26 Sep 2008 05:13:55 GMT
Server: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch10
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

f3
<h1>Software error:</h1>
<pre>Malformed multipart POST
</pre>
<p>
For help, please send mail to the webmaster (<a href="mailto:webmaster@localhost">webmaster@localhost</a>), giving this error message
and the time and date of the error.

</p>

My post request is as follows
POST HTTP/1.1
Accept-Language: en-us
Content-Type: multipart/form-data; boundary=---------------------------7d2b119100532
User-Agent: Mozilla/3.01 (compatible)
Host: 192.168.2.5
Pragma: no-cache
Content-Length: 717

-----------------------------7d2b119100532
Content-Disposition: form-data; name="field1"

5107115015_auto_end
-----------------------------7d2b119100532
Content-Disposition: form-data; name="flat_file"; filename="travellerdata.dat"
Content-Type: text/plain

<SYSSN>5107115015</SYSSN>
<HDD slot="0">
<serial>DA40P7C003P5</serial>
<model>MAW3300NC</model>
<firmware>0104</firmware>
</HDD>
<network>
<adapter slot="1">
<interface slot="1">
<mac>00:E0:81:4B:8F:FD</mac>
</interface>
</adapter>
</network>
<BIOS>
<revision></revision>
<date>06/23/06</date>
</BIOS>
<CPU_count>4</CPU_count>
<CPU slot="0">
<serial>00020F120000000000000000</serial>
</CPU>
-----------------------------7d2b119100532--

Appreciate if you can point out where I am going wrong.

Thanks,
tewari
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top