I’m getting the body {"errors":null,"success":null}
when I run my PHP code. When I run the test in, I see Postman that a successful response is more verbose. The logs don’t offer any clues:
2023-09-26T06:59:17.403857369Z: WEB ▶ 172.18.0.5 PUT 200 /api/v1/tasks/11091/attachments 2.8333ms - GuzzleHttp/7
Any insight would be much appreciated. Thank you!
Can you share your code? To me this looks like you don’t pass the upload file properly.
I threw a lot of spaghetti at the wall, but this is what finally gave me a 200:
// Sets up the auth header and no others. I've been using this for all my requests, so I'm fairly confident there's no problem here.
$headers = VikunjaHelper::getHeaders();
$client = new GuzzleHttp\Client(['base_uri' => $url]);
$body = Psr7\Utils::tryFopen($this->localPath, 'r');
$options = [
'headers' => $headers,
'multipart' => [
[
'name' => $this->fileName,
'contents' => $body,
'headers' => $headers
]
]
];
$r = $client->request('PUT', $url, $options);
Let me know if you see anything wrong. I see the headers are sent twice, but when I populated only one, I got an error, the details of which I don’t remember.
Here’s the relevant Guzzle documentation: Request Options — Guzzle Documentation
When I tried using a different type of Guzzle request having added the Content-Type header myself, I got an error in the Vikunja logs about Boundary not being set. I tried tossing in any old value just to see what would happen, but I got a different error (again, don’t remember the details). The way I read the Guzzle documentation, ‘multipart’ is the only way Guzzle will add the Content-Type header itself and thus deal with the Boundary value correctly.
I would love to hear your thoughts.
Many thanks!
Glad you figured it out!
Multipart Form is the correct way to do this. See also the docs: Vikunja API documentation
I can imagine Guzzle is smart enough to send the header only once if you provide it multiple times.
I’m sorry, I was unclear. I didn’t figure out. That’s the code that gives me the 200 but doesn’t result in the attachment uploading.
Still working on this. I mentioned that it works in Postman. The PHP code generated by Postman generates results in the same {"errors":null,"success":null}
but no attachment made.
This is the generated PHP:
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'http://[IP]/api/v1/tasks/11605/attachments',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => array('files' => fopen('/home/kj/scripts/attachments/1696993909.jpg', 'r')),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer [token]'
),
));
Any idea what am I/is Postman doing wrong?
Thanks!
A curl request like this works fine:
curl 'http://localhost:3456/api/v1/tasks/1140/attachments' \
-X 'PUT' \
-H "Authorization: Bearer $BEARER" \
-F "files=@/path/to/file"
According to chatgpt, this is the equivalent php code:
<?php
// Replace these variables with your actual values
$apiEndpoint = 'http://localhost:3456/api/v1/tasks/1140/attachments';
$bearerToken = 'YOUR_BEARER_TOKEN';
$filePath = '/path/to/file';
// Initialize cURL session
$ch = curl_init($apiEndpoint);
// Set cURL options
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $bearerToken,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'files' => new CURLFile($filePath),
]);
// Execute the cURL request
$response = curl_exec($ch);
// Check for cURL errors and handle the response as needed
if ($response === false) {
echo 'cURL error: ' . curl_error($ch);
} else {
echo 'Response: ' . $response;
}
// Close cURL session
curl_close($ch);
Does thatt work?