如何在 PHP 中直接从数组以编程方式 HTTP POST CSV 文件


How to programatically HTTP POST a CSV file directly from an array in PHP?

我正在为 opencellid.org 网站贡献数据。他们有几个 API 选项来提交数据,但唯一的批量方法需要使用 HTTP POST 文件上传,并将 API 密钥作为 POST 字段。可接受的格式是CSV,JSON和CLF3。我将数据存储在SQL数据库中供内部使用,并定期将数据提交给opencellid。

目前,我用于将数据提交到 opencellid 的脚本会查询 SQL 数据库以获取最新的测量值,然后将其保存为服务器上的 CSV 文件,然后立即通过 HTTP POST 上传。在我眼里,这是不优雅的。

所以我的问题是,您能否直接从数组上传 CSV 文件,而无需首先在服务器上实际创建 CSV 文件?

这是我们目前使用的代码片段。

//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);

任何人都可以建议一种直接从数组上传 CSV 的方法吗?

我设法使用 fputcsv 将 csv 数据捕获到变量中,以 php://output 输出缓冲。 由于该服务仅允许提交多部分格式,因此需要像这样构造有效负载。

<?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);

我收到 API 密钥错误,但它应该可以工作。

Intreeting问题。我唯一能想到的是,你用帖子的标题回显"csv 数据",它是一个 csv 文件。这不应该在服务器 afaik 上创建文件。不确定如何处理它,但是如果您运行设置apache标头或正在使用的任何服务器系统。试一试,让我知道它是否有效。