How do I upload a file to S3 from GuzzleHttp\Psr7\Stream?

205 Views Asked by At

I'm using aws-php-sdk to save Outlook email attachments to S3. I'm able to upload the file to S3 but when I download the file and open it I only see the content byte data. I don't know how to store the content of the file using contentbytes. I've tried $attachment->getContentBytes()->getContents() but that always uploads a 0kb file and $attachment->getContentBytes() displays the content bytes when I open the file.

The FileAttachment is from msgraph-sdk-php which I'm using to get the Outlook email attachments.

private function saveToS3(string $s3_directory, \Microsoft\Graph\Model\FileAttachment $attachment)
{
  $aws_s3_key    = 'XXXXXXX';
  $aws_s3_secret = 'XXXXXXXX';
  $aws_s3_region = 'us-west-1';
  $aws_bucket    = 'test-storage';

  $s3Client = new S3Client([
      'version'     => 'latest',
      'region'      => $aws_s3_region,
      'credentials' => [
          'key'    => $aws_s3_key,
          'secret' => $aws_s3_secret,
      ],
  ]);

  return $s3Client->putObject([
      'Bucket'      => $aws_bucket,
      'Key'         => $s3_directory,
      'Body'        => $attachment->getContentBytes(),
      'ContentType' => $attachment->getContentType(),
  ]);
}

A sample FileAttachment:

{
  "@odata.type": "#microsoft.graph.fileAttachment",
  "@odata.mediaContentType": "application/octet-stream",
  "id": "AAMkAGQyMzYyNXXXXXXXXXXXXXXXxLjl14fH8FdpE=",
  "lastModifiedDateTime": "2023-07-31T22:43:52Z",
  "name": "README.md",
  "contentType": "application/octet-stream",
  "size": 1708,
  "isInline": false,
  "contentId": "f_leudosmi0",
  "contentLocation": null,
  "contentBytes": "IyBDUk0gaW5XXXXXXXXXXXXXXXXXXXXXgZnJhbWV3b3JrIAo="
}

How do I upload the file contents and not the content bytes to S3?

1

There are 1 best solutions below

1
Muhammad Sumon Molla Selim On BEST ANSWER

You can base64_decode the content bytes and send it to S3.

return $s3Client->putObject([
    'Bucket'      => $aws_bucket,
    'Key'         => $s3_directory,
    'Body'        => base64_decode($attachment->getContentBytes()->getContents(), true),
    'ContentType' => $attachment->getContentType(),
]);

Another solution could be, create and save the file from the content bytes.

$content = base64_decode($attachment->getContentBytes()->getContents(), true);
file_put_contents($attachment->getname(), $content);

Then, you can pass the file to S3.

return $s3Client->putObject([
    'Bucket'      => $aws_bucket,
    'Key'         => $s3_directory,
    'SourceFile'  => $attachment->getname(),
    'ContentType' => $attachment->getContentType(),
]);