How to get the image file of a ticket article attachment via Zammad API

  • Used Zammad Version 5.3.x

  • Subscribed hosted Zammad

  • Zammad API related question

  • Using zammad-api-client-php

Using the Zammad API, I need to get (read) the attachment content of a ticket article, which is an image file, and store that image on my server for further processing.

I tried fopen(), file_get_contents() and stream_get_contents() but no luck, I’m getting an empty string. Maybe I need to access the Guzzle stream object and read that stream, but I don’t know how to. Any help or hint into the right direction would be highly appreciated.

Example array of the ticket article attachment:

article_attachments: Array
[0] => Array
    [id] => 132
    [store_file_id] => 110
    [filename] => image.png
    [size] => 268680
    [preferences] => Array
        [Content-Type] => image/png
        [resizable] => 1
        [content_preview] => 1

Example object of the ticket article attachment (id:132) content:

GuzzleHttp\Psr7\Stream Object
    [stream:GuzzleHttp\Psr7\Stream:private] => Resource id #45
    [size:GuzzleHttp\Psr7\Stream:private] => 
    [seekable:GuzzleHttp\Psr7\Stream:private] => 1
    [readable:GuzzleHttp\Psr7\Stream:private] => 1
    [writable:GuzzleHttp\Psr7\Stream:private] => 1
    [uri:GuzzleHttp\Psr7\Stream:private] => php://temp
    [customMetadata:GuzzleHttp\Psr7\Stream:private] => Array


Found the solution. In short:
I actually need to access the “body” or content of the GuzzleHttp\Psr7\Stream Object that I receive with article method: getAttachmentContent(‘attachment_id’).

In case anyone else has this problem to solve, I’ll post my long version of the solution below using the Zammad API PHP Client. If anyone has a more elegant solution, I’d be interested.

// Get the ticket object.
$ticket = $client->resource( ResourceType::TICKET )->get($ticket_id);

// Get the ticket articles. 
$ticket_articles = $ticket->getTicketArticles();

// Loop $ticket articles to get the article attachments.
foreach($ticket_article_ids as $key => $article_id) {

	// Get an article object.
	$article = $client->resource( ResourceType::TICKET_ARTICLE )->get($article_id);

	// Get the article attachments (array).
	$article_attachments = $article->getValue('attachments');

	// Loop the article attachments.
	foreach($article_attachments as $key => $attachment) {

		// Get the attachment content. 
		// Note: This returns a GuzzleHttp\Psr7\Stream Object
		$attachment_content = $article->getAttachmentContent($attachment['id']);

		// Get the Guzzle object "body" or contents, in my case the image file.
		$guzzle_contents = $attachment_content->getContents();

		// .. process the image file .. i.e. store on server under new name.
		$server_filename = "./files/ticket123-article45-" . $attachment['filename'];
		// Response contains the amount of bytes of the file or FALSE.
		$response = file_put_contents($server_filename, $guzzle_contents)
		// ... do some more stuff ..
1 Like

@joB good to see you found a solution. I also need to pull attachments, I use n8n and asked in their forum, the workflow is shown here.

Do you maybe also try to “export” the whole ticket for putting it elsewhere? I am trying to generate a pdf etc. and look for ways to do that. Maybe you are ahead of me on that path :wink:

@sgw thanks for you comments.

In my current project I do not export a whole ticket but only need some information from it, create another kind of “ticket” for another system and upload this newly formatted information to another server for further processing.

To create a PDF from ticket data using PHP I would give dompdf a try. It says in its headline “Dompdf is an HTML to PDF converter” but you can feed it with whatever data as long as you convert it before in digestible input (strings) for dompdf. It’s very flexible.

How to do that is explained very straight forward in this video. It mentions all the basics and gives a good starting point.

Hopefully I did not misunderstood your requirements. If so, please give me a note.

I’m closing this as off topic. The original topic has been solved and then was hijacked. Sorry but I personally don’t support this kind of behavior.