Jump to content

upload files from php server to c++ client using curl


jazz15

Recommended Posts

22 hours ago, gw1500se said:

"http://localhost//Download//info.txt" needs to be the PHP script that returns any files ready for download. You did not post the code where you read the result from the curl_easy_perform.

here is the code but the issue is i want to return an array containing names how do i get it in c++ in array form so i can iterate over it one by one.

#define CURL_STATICLIB
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <curl.h>

using namespace std;
size_t size = 0;

size_t write_to_string(void *ptr, size_t size, size_t count, void *stream) {
	((string*)stream)->append((char*)ptr, 0, size*count);
	return size*count;
}
int main() {
	CURL *curl;
	CURLcode res;
	curl_global_init(CURL_GLOBAL_ALL);
	curl = curl_easy_init();
	if (curl)
	{
		string out = string("htt://file.php");
		curl_easy_setopt(curl, CURLOPT_URL, out.c_str());
		string response;
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_to_string);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
		res = curl_easy_perform(curl);
	   
		cout << "Variable response : " << response.c_str();
		if (res != CURLE_OK)
			fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
		curl_easy_cleanup(curl);
	}
	curl_global_cleanup();
	system("pause");
	return 0;
}
<?php
//$Aid = $_REQUEST['Aid'];
//$Acd = $_REQUEST['Acd'];
$Aid='test';
$Acd='test2';
$data = array();
$data[] = array('Aid_response'=> $Aid, 'Acd_response'=> $Acd);
//echo json_encode($data);

?>

this php script is just for testing data.ultimately i will be sending names of the files available in download folder on server and then i will be passing these file names in another post request to download the file.

Link to comment
Share on other sites

You can't. You need to take the output from the PHP script and process it into an array in c++. What format did you choose to return in the PHP script? If JSON then you need to use c++ json decode to convert it to an array.

Edited by gw1500se
Link to comment
Share on other sites

<?php


$send=array();
$files = glob("path/Downloads/*.txt");

foreach ($files as $key => $val) {

 $send[]= basename($val);
}

if(!empty($send))
{
echo json_encode($send);
}
else{
  echo 'empty!';
}

?>

so far i am able to get all names of .txt files in my c++ client side in jsonencoded form..now only thing left is to store these filenames in an array in c++.after which i can focus on how to get acknowledgement that file was successfully downloaded by the client so that it can be deleted from the server safely

this is the format i am getting ["text2.txt","text3.txt","text4.txt"]

Edited by jazz15
Link to comment
Share on other sites

1 hour ago, gw1500se said:

That is a JSON string. Cereal will do what you want in c++.

i didn't get that so this is what i did which is not good but it is what it is...

char chars[] = "[]\"";

		for (unsigned int i = 0; i < strlen(chars); ++i)
		{
			// you need include <algorithm> to use general algorithms like std::remove()
			response.erase(std::remove(response.begin(), response.end(), chars[i]), response.end());
		}
		string ter;
	
		const char s[2] = ",";
		char *token;
		char* c = const_cast<char*>(response.c_str());
		/* get the first token */
		token = strtok(c, s);

		/* walk through other tokens */
		while (token != NULL) {
			printf(" %s\n", token);
	
			int i = 0;
			ter.append(token);
			ter.append("\n");
			token = strtok(NULL, s);
		}
		istrstream uy(ter.c_str());
		string line;
		while (std::getline(uy, line)) {
			cout << line<<endl;
		}

now i need some kind of affirmation from the client side to the server side after successfully downloading the file on client side so that file on server folder can be deleted.or is there any other good method for this affirmation so i get acknowledgement that file was successfully downloaded on client pc?

Link to comment
Share on other sites

this is the proper way to send names of files along with the size of files

#define CURL_STATICLIB
//#define JSON_DLL
using namespace std;
#include <cstdint>
#include <iostream>
#include <memory>
#include <string>

#include <curl.h>
#include<json\reader.h>
#include <json/json.h>
#pragma warning( disable : 4996)

namespace
{
	std::size_t callback(
		const char* in,
		std::size_t size,
		std::size_t num,
		std::string* out)
	{
		const std::size_t totalBytes(size * num);
		out->append(in, totalBytes);
		return totalBytes;
	}
}

int main()
{
	const std::string url("http://localhost/file.php");

	CURL* curl = curl_easy_init();

	// Set remote URL.
	curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

	// Don't bother trying IPv6, which would increase DNS resolution time.
	curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);

	// Don't wait forever, time out after 10 seconds.
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);

	// Follow HTTP redirects if necessary.
	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);

	// Response information.
	long httpCode(0);
	std::unique_ptr<std::string> httpData(new std::string());

	// Hook up data handling function.
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);

	// Hook up data container (will be passed as the last parameter to the
	// callback handling function).  Can be any pointer type, since it will
	// internally be passed as a void pointer.
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());

	// Run our HTTP GET command, capture the HTTP response code, and clean up.
	curl_easy_perform(curl);
	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
	curl_easy_cleanup(curl);

	if (httpCode == 200)
	{
		std::cout << "\nGot successful response from " << url << std::endl;

		// Response looks good - done using Curl now.  Try to parse the results
		// and print them out.
		Json::Value jsonData;
		Json::Reader jsonReader;
	//	Json::arrayValue jsonArray;
		
			if (jsonReader.parse(*httpData.get(), jsonData))
			{
				for (Json::Value::ArrayIndex i = 0; i != jsonData.size(); i++)
				{
					std::cout << "Successfully parsed JSON data" << std::endl;
					std::cout << "\nJSON data received:" << std::endl;
					std::cout << jsonData.toStyledString() << std::endl;

					const std::string Name(jsonData[i]["Name"].asString());

					const std::string Size(jsonData[i]["Size"].asString());

					std::cout << "Natively parsed:" << std::endl;
					std::cout << "\tName: " << Name << std::endl;
					std::cout << "\tSize: " << Size << std::endl;
					std::cout << std::endl;
				}
			}
			else
			{
				std::cout << "Could not parse HTTP data as JSON" << std::endl;
				std::cout << "HTTP data was:\n" << *httpData.get() << std::endl;
				return 1;
			}
		
	}
	else
	{
		std::cout << "Couldn't GET from " << url << " - exiting" << std::endl;
		return 1;
	}

	return 0;
}

and this is the php script

<?php
$send=array();
$size=array();
$files = glob("Downloads/*.txt");
foreach ($files as $key => $val) {

 $send[]=array('Name'=>basename($val),'Size'=>filesize($val));

}

if(!empty($send))
{
echo json_encode($send);

}
else{
  echo 'empty!';
}

?>

 

Link to comment
Share on other sites

Not quite. That will create a JSON array with the name and size as separate entries. You want each name to be associated with its specific size so create an array of arrays.

$send=[];
foreach ($files as $key => $val) {

 $send+=array('Name'=>basename($val),'Size'=>filesize($val));

}

Then on the c++ side you will have an array of n entries where each entry contains an array with the key 'name' and 'size' with their respective values.

 

Link to comment
Share on other sites

 

36 minutes ago, gw1500se said:

 

Then on the c++ side you will have an array of n entries where each entry contains an array with the key 'name' and 'size' with their respective values.

 

 

 

Capture.JPG

Edited by jazz15
privacy
Link to comment
Share on other sites

1 minute ago, gw1500se said:

There you go. Just JSON decode it in c++.

actually i  posted the above screenshot to show that this is what i get with my php script..when i changed it with $send+ like you have posted above it showed only the first record

Link to comment
Share on other sites

11 minutes ago, gw1500se said:

Did you initialize the array like I showed?


$send=[];

 

i intialized it like this $send=array();

or even with this initialization $send=[]; it won't work because syntax is not correct

Edited by jazz15
Link to comment
Share on other sites

8 minutes ago, gw1500se said:

My bad. It has been a while since I did this. Your previous code is correct as is the image you posted of the result. Sorry. So where are you stuck now?

some way to acknowledge on server that file was downloaded by the client...i can do this with calling another php script but i want some method to send acknowledgement through the same request in which client side is going to download the file..let me work on that and i,ll get back with full code

Link to comment
Share on other sites

25 minutes ago, gw1500se said:

How can you know the download was successful before the download completes?

so it means i need to send a request again on the server for e.g on result.php after downloading the file that file was successfully downloaded at client's pc?after that i can have a script in result.php that gets filename and size from client pc which was downloaded on client pc and write it to some text file that this file with blah size was downloaded at blah blah time  by the cleint's pc

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.