php - PHP curl文件传输
问题描述
我们正在使用 GLPI API,我们需要创建与文档链接的票证。
我无法翻译的唯一卷曲部分是文档的上传。
使用卷曲(工作):
curl -i -X POST "http://glpitest/glpi/apirest.php/Document" -H "Content-Type: multipart/form-data" -H "Session-Token:sessiontoken"-H "App-Token:apptoken" -F "uploadManifest={\"input\": {\"name\": \"Uploaded document\", \"_filename\" : \"test.txt\"}};type=application/json" -F "filename[0]=@test.txt" "http://glpitest/glpi/apirest.php/Document"
但我不能翻译这是在 PHP CURL 我试过这样的事情:
$headers = array(
'Authorization: Basic ' . $_SESSION['encodelogin'],
'App-Token:' . $_SESSION['app_token'], // <---
'Session-Token:' . $_SESSION['session_token'],
'Http_Accept: application/json',
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_exec($ch);
echo $url = $_SESSION['api_url'] . "/Document";
$cfile = new CURLFile('testpj.txt', 'text/plain', 'test_name');
//$manifest = 'uploadManifest={"input": {"name": "test", "_filename" : "testpj.txt"}};type=application/json filename[0]=@'+$cfile;
$post = ["{\"input\": {\"name\": \"test\", \"_filename\" : \"testpj.txt\"}};type=application/json}", @"C:\\xampp\htdocs\glpi"];
print_r($post);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
api中的示例:
$ curl -X POST \
-H 'Content-Type: multipart/form-data' \
-H "Session-Token: 83af7e620c83a50a18d3eac2f6ed05a3ca0bea62" \
-H "App-Token: f7g3csp8mgatg5ebc5elnazakw20i9fyev1qopya7" \
-F 'uploadManifest={"input": {"name": "Uploaded document", "_filename" : ["file.txt"]}};type=application/json' \
-F 'filename[0]=@file.txt' \
'http://path/to/glpi/apirest.php/Document/'
< 201 OK
< Location: http://path/to/glpi/api/Document/1
< {"id": 1, "message": "Document move succeeded.", "upload_result": {...}}
更新:我试过@hanshenrik 但我有一个错误。
["ERROR_JSON_PAYLOAD_INVALID","JSON 有效负载似乎无效"]
在 api.class.php :
if (strpos($content_type, "application/json") !== false) {
if ($body_params = json_decode($body)) {
foreach ($body_params as $param_name => $param_value) {
$parameters[$param_name] = $param_value;
}
} else if (strlen($body) > 0) {
$this->returnError("JSON payload seems not valid", 400, "ERROR_JSON_PAYLOAD_INVALID",
false);
}
$this->format = "json";
} else if (strpos($content_type, "multipart/form-data") !== false) {
if (count($_FILES) <= 0) {
// likely uploaded files is too big so $_REQUEST will be empty also.
// see http://us.php.net/manual/en/ini.core.php#ini.post-max-size
$this->returnError("The file seems too big!".print_r($_FILES), 400,
"ERROR_UPLOAD_FILE_TOO_BIG_POST_MAX_SIZE", false);
}
// with this content_type, php://input is empty... (see http://php.net/manual/en/wrappers.php.php)
if (!$uploadManifest = json_decode(stripcslashes($_REQUEST['uploadManifest']))) {
//print_r($_FILES);
$this->returnError("JSON payload seems not valid", 400, "ERROR_JSON_PAYLOAD_INVALID",
false);
}
我在 $_REQUEST 中没有 uploadManifest,如果我把文件名 [0] 文件放在我有 curl 错误 26 (can't read file) 。
谢谢
解决方案
翻译
-F "uploadManifest={\"input\": {\"name\": \"Uploaded document\", \"_filename\" : \"test.txt\"}};type=application/json"
很棘手,因为 php 并没有真正支持向多部分请求的成员添加 Content-Type 标头(或任何标头),唯一的*例外*(我知道)是 CURLFile 的“Content-Type”和 Content -Disposition 的“文件名”标头...考虑到这一点,您可以通过将数据放入文件并围绕该虚拟文件创建 CURLFile() 来解决此问题,但它.. 看起来很棘手且愚蠢(因为 PHP 的 curl api 包装器缺乏对它的适当支持)
使用 CURLFile 解决方法,它看起来像:
<?php
declare(strict_types = 1);
$ch = curl_init();
$stupid_workaround_file1h = tmpfile();
$stupid_workaround_file1f = stream_get_meta_data($stupid_workaround_file1h)['uri'];
fwrite($stupid_workaround_file1h, json_encode(array(
'input' => array(
'name' => 'Uploaded document',
'_filename' => 'test.txt'
)
)));
curl_setopt_array($ch, array(
CURLOPT_URL => "http://glpitest/glpi/apirest.php/Document",
CURLOPT_POST => 1,
CURLOPT_HEADER => 1,
CURLOPT_HTTPHEADER => array(
"Session-Token:sessiontoken",
"App-Token:apptoken"
),
CURLOPT_POSTFIELDS => array(
'uploadManifest' => new CURLFile($stupid_workaround_file1f, 'application/json', ' '), // https://bugs.php.net/bug.php?id=79004
'filename[0]' => new CURLFile('test.txt', 'text/plain')
)
));
curl_exec($ch);
curl_close($ch);
fclose($stupid_workaround_file1h);
推荐阅读
- r - 选择仅包含数值 >= 0 的列
- azure - 将 Azure Functions 从“消费计划”切换到“高级计划”
- python-3.x - 在 RSS 源上使用美丽的汤按日期和关键字过滤
- java - 我的数据库没有更新列上的条目
- c# - 如何在 .net 标准库中获得对 ARCGISRuntime SystemLocationDataSource 的引用?
- amazon-web-services - 与 AWS/S3 的 PUT 请求等效的“If-Match”或“x-goog-if-generation-match”
- python - 通过比较列值上的字符串来过滤 python Dataframe
- c# - 将键值对字符串转换为 .NET 对象
- python - 如何在postgres的列表中插入字典中的值/键
- soundcloud - SoundCloud API - “同一首歌”的限制?/403 问题?