I'm contributing data to the opencellid.org website. They have several API options to submit data but the only bulk method requires an HTTP POST file upload with the API key as a POST field. Formats acceptable are CSV, JSON and CLF3. I store the data in an SQL database for internal use and periodically submit data to opencellid.
At the moment the script that I use to submit the data to opencellid queries the SQL DB for the most recent measurements and then saves it as a CSV file on the server and then immediately uploads it via HTTP POST. In my eyes this is inelegant.
So my question is, can you POST upload a CSV file directly from an array without first having to actually create a CSV file on the server?
Here's the code snippet we currently use.
//Create and save CSV
$output = fopen("opencellid.csv","w") or die();
fputcsv($output, array_keys($celldata[0]));
foreach($celldata as $cell) {
fputcsv($output, $cell);
}
fclose($output) or die();
//Upload CSV
$target_url = 'http://opencellid.org/measure/uploadCsv';
$file_name_with_full_path = realpath('./opencellid.csv');
$post = array('key' => 'opencellidapikey',
'datafile'=>'@'.$file_name_with_full_path.";type=text/plain");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$target_url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$postresult = curl_exec ($ch);
Can anyone suggest a way to directly upload a CSV from an array?
I managed to capture the csv data in to a variable using fputcsv to php://output with output buffering. Since the service only allows multipart format for the submission, you need to construct the payload like this.
<?php
//Construct your csv data
$celldata = array(
array(
"heading1",
"heading2",
"heading3",
),
array(
1,
2,
3,
),
array(
4,
5,
6,
)
);
//Output to php://output
ob_start();
$outstream = fopen("php://output", 'w');
foreach($celldata as $cell) {
fputcsv($outstream, $cell);
}
fclose($outstream) or die();
$csv_data = ob_get_clean();
$url = 'http://opencellid.org/measure/uploadCsv';
// Taken from http://stackoverflow.com/questions/3085990/post-a-file-string-using-curl-in-php
// form field separator
$delimiter = '-------------' . uniqid();
// file upload fields: name => array(type=>'mime/type',content=>'raw data')
$fileFields = array(
'datafile' => array(
'type' => 'text/plain',
'content' => $csv_data,
),
);
// all other fields (not file upload): name => value
$postFields = array(
'key' => 'opencellidapikey', //Put your api key here
);
$data = '';
// populate normal fields first (simpler)
foreach ($postFields as $name => $content) {
$data .= "--" . $delimiter . "\r\n";
$data .= 'Content-Disposition: form-data; name="' . $name . '"';
$data .= "\r\n\r\n";
$data .= $content;
$data .= "\r\n";
}
// populate file fields
foreach ($fileFields as $name => $file) {
$data .= "--" . $delimiter . "\r\n";
$data .= 'Content-Disposition: form-data; name="' . $name . '";' .
' filename="' . $name . '"' . "\r\n";
$data .= 'Content-Type: ' . $file['type'] . "\r\n";
$data .= "\r\n";
$data .= $file['content'] . "\r\n";
}
$data .= "--" . $delimiter . "--\r\n";
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_POST, true);
curl_setopt($handle, CURLOPT_HTTPHEADER , array(
'Content-Type: multipart/form-data; boundary=' . $delimiter,
'Content-Length: ' . strlen($data)));
curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
curl_setopt($handle, CURLOPT_RETURNTRANSFER,1);
$result = curl_exec($handle);
var_dump($result);
I get API key error, but it should work.