Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

uniqueginun's avatar

send UploadedFile instances using Http client

Hello everyone,

I have this scenario where I send post request from my Laravel app to another Laravel app and the other Laravel app send it using Http client

public function store(FormRequest $request)
    {
        $response = Http::attach(
                'attachment', $request->file('attach'), 'attachment.pdf'
            )
        ->post('second/app/url', [
            'user_info' => $request->userInfo(),
            'service_info' => $request->serviceInfo(),
        ]);
    }

it gives InvalidArgumentException: A 'contents' key is required

How do I send it, also sometimes I need to send multiple files coming from FormRequest $request

0 likes
17 replies
Sinnbeck's avatar

The second argument should be a string

$response = Http::attach(
                'attachment', $request->file('attach')->getContent(), 'attachment.pdf'
            )
        ->post('second/app/url', [
            'user_info' => $request->userInfo(),
            'service_info' => $request->serviceInfo(),
        ]);

And you can use attach() multiple times

Sinnbeck's avatar

@uniqueginun Ok where is that error thrown then? And do you get data if you do dd($request->file('attach')->getContent());

uniqueginun's avatar

@Sinnbeck here is the full error:

InvalidArgumentException: A 'contents' key is required in file /var/www/html/vendor/guzzlehttp/psr7/src/MultipartStream.php on line 84

And yes I do get the content when dump that line

Sinnbeck's avatar

@uniqueginun Well if that works, it might be easier to work backwards from there :) Get it working first, and then optimize

uniqueginun's avatar

@Sinnbeck

Look interesting: this code gives same error

InvalidArgumentException: A 'contents' key is required in file /var/www/html/vendor/guzzlehttp/psr7/src/MultipartStream.php on line 84

$pdfFilePath = storage_path('app/attachments/myattach.pdf');
$request->generatePdf()->save($pdfFilePath);

 $response = Http::attach('myattach', File::get($pdfFilePath), 'myattach.pdf')			

even though I checked the file was there

Sinnbeck's avatar

@uniqueginun I did some digging. Seems that when attaching files, the second argument in post() needs to be an array of arrays.

$response = Http::attach(
                'attachment', $request->file('attach')->getContent(), 'attachment.pdf'
            )
        ->post('second/app/url', [
[           
           'user_info' => $request->userInfo(),
            'service_info' => $request->serviceInfo(),
],
        ]);
uniqueginun's avatar

@Sinnbeck the post data is being sent successfully and I get them in the other side the issue is how to attach this file I get from the first request

Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

@uniqueginun Let me try again. When you attach a file, the Http request changes to a multi-part request. That means that it holds more than one type of data. To mitigate this you need to set the second parameter of post() to an array within an array.. Check my example above or this post: https://stackoverflow.com/a/68409134/1305117

uniqueginun's avatar

@Sinnbeck Ohhhhhhhhhhhhhhh. yeah yeah. it works thank you now I understand. it is not that clear in the docs.

idayac's avatar

@Sinnbeck im trying to upload an audio file (created using faker) to the above and getting the same error . will you be able to help me to fix this ?

murilo's avatar

I had the same problem . try to use this in the paramter that you gonna send -

 $response = Http::withHeaders($this->header)
          ->attach('image_profile', file_get_contents($image_profile->getPathname()), $image_profile->getClientOriginalName() )
            ->post($this->request_host.'/api/admin/users/store', $this->transformMultiFormData($params));  

  private function transformMultiFormData ($data) {
        $output = [];

        foreach($data as $key => $value){
            if(!is_array($value)){
                $output[] = ['name' => $key, 'contents' => $value];
                continue;
            }

            foreach($value as $multiKey => $multiValue){
                $multiName = $key . '[' .$multiKey . ']' . (is_array($multiValue) ? '[' . key($multiValue) . ']' : '' ) . '';
                $output[] = ['name' => $multiName, 'contents' => (is_array($multiValue) ? reset($multiValue) : $multiValue)];
            }
        }
        return $output;
    }

instead send the value like this -

[
  "status" => "active",
  "name" => "joe",
  "folder" => "123",
  "password" => "123456",
  "email" => "joe233@gmail",
  "image_profile" => "image.jpg",
   "admin_info" =>  [
    "name" => "joe",
    "last_name" => "bob"
    ]
  ]

the transformMultiFormData will convert into that s -

  [
      ["name" => "status" , "contents" => "active"],
      ["name" => "name" , "contents" => "joe"],
      ["name" => "folder" , "contents" => "123"],
      ["name" => "password" , "contents" => "123456"],
      ["name" => "email" , "contents" =>"joe233@gmail"],
      [  'name' => 'image_profile', 'contents' => 'image.jpg'  ],
      ['name' => 'admin_info', 'contents' => [
             ['name' => 'name', 'contents' => "joe"],
             ['name' => 'last_name', 'contents' => "bob"]
      ]],

    ]

I didnt understand why , but it worked .

1 like
harp-eng's avatar

$data = [ 'name' => $request->get('full_name'), 'email' =>$request->get('email') ];

I changed the above array format to the below-given array format, and it started working for me.

$data = [ [ 'name' => 'full_name', 'contents' => $request->get('full_name') ], [ 'name' => 'email', 'contents' => $request->get('email') ] ];

1 like

Please or to participate in this conversation.