Reputation: 37
I'm trying to upload an image to HipChat with CPPREST SDK with no success. There are examples for uploading images to other servers, but the HipChat API seems more complex (being very new to this I couldn't fill in the gaps...).
From HipChat REST API documentation (https://www.hipchat.com/docs/apiv2/method/share_file_with_room):
Share a file with the room.
Format the request as multipart/related with a single part of content-type application/json and a second part containing your file.
NOTE: The part containing the file must include name="file" in the part's Content-Disposition header. The application/json part containing a message is optional and can be excluded, but a file part is required
Example Request:
Headers:
Content-Type: multipart/related; boundary=boundary123456
Body:
--boundary123456 Content-Type: application/json; charset=UTF-8
Content-Disposition: attachment; name="metadata"
{"message": "Check out this file upload!"}
--boundary123456 Content-Type: image/png
Content-Disposition: attachment; name="file"; filename="upload.png"
"file content goes here"
--boundary123456--
I'm trying to use the set_body() method: void web::http::http_request::set_body(const concurrency::streams::istream& stream, ....) but I cannot figure out how to insert the file stream inside all the above complex body. The documentation of set_body() says: "This cannot be used in conjunction with any other means of setting the body of the request". Do I need to read the file into a string and embed where it says "file content goes here", and use one of the other set_body() methods, instead of using the set_body() method with the file stream?
Thanks, Ofer
Upvotes: 1
Views: 710
Reputation: 866
FYI
/**
* Share file with room
* More info: https://www.hipchat.com/docs/apiv2/method/share_file_with_room
*
* @param string $id The id or name of the room
* @param array $content Parameters be posted for example:
* array(
* 'name' => 'Example name',
* 'privacy' => 'private',
* )
*
* @return \Psr\Http\Message\ResponseInterface
* @throws
*/
public function sharefileWithRoom($id, $file)
{
$url = $this->baseUrl . "/v2/room/{$id}/share/file";
$headers = array(
'Authorization' => $this->auth->getCredential()
);
$parts[] = [
'headers' => [
'Content-Type' => $file['file_type'] ?: 'application/octet-stream',
],
'name' => 'file',
'contents' => stream_for($file['content']),
'filename' => $file['file_name'] ?: 'untitled',
];
if (! empty($file['message'])) {
$parts[] = [
'headers' => [
'Content-Type' => 'application/json',
],
'name' => 'metadata',
'contents' => json_encode(['message' => $file['message']]),
];
}
return $response = $this->postMultipartRelated($url, [
'headers' => $headers,
'multipart' => $parts,
]);
}
/**
* Make a multipart/related request.
* Unfortunately Guzzle doesn't support multipart/related requests out of the box.
*
* @param $url
* @param $options
* @return \Psr\Http\Message\ResponseInterface
*/
protected function postMultipartRelated($url, $options)
{
$headers = isset($options['headers']) ? $options['headers'] : [];
$body = new MultipartStream($options['multipart']);
$version = isset($options['version']) ? $options['version'] : '1.1';
$request = new Request('POST', $url, $headers, $body, $version);
$changeContentType['set_headers']['Content-Type'] = 'multipart/related; boundary='.$request->getBody()->getBoundary();
$request = modify_request($request, $changeContentType);
$client = new HttpClient;
return $client->send($request);
}
Upvotes: 0