Skip to content

Instantly share code, notes, and snippets.

@maxivak
Last active March 21, 2026 03:44
Show Gist options
  • Select an option

  • Save maxivak/18fcac476a2f4ea02e5f80b303811d5f to your computer and use it in GitHub Desktop.

Select an option

Save maxivak/18fcac476a2f4ea02e5f80b303811d5f to your computer and use it in GitHub Desktop.
PHP upload file with curl (multipart/form-data)

We want to upload file to a server with POST HTTP request. We will use curl functions.


// data fields for POST request
$fields = array("f1"=>"value1", "another_field2"=>"anothervalue");

// files to upload
$filenames = array("/tmp/1.jpg", "/tmp/2.png");

$files = array();
foreach ($filenames as $f){
   $files[$f] = file_get_contents($f);
}

// URL to upload to
$url = "http://site.com/upload";


// curl

$curl = curl_init();

$url_data = http_build_query($data);

$boundary = uniqid();
$delimiter = '-------------' . $boundary;

$post_data = build_data_files($boundary, $fields, $files);


curl_setopt_array($curl, array(
  CURLOPT_URL => $url,
  CURLOPT_RETURNTRANSFER => 1,
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  //CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POST => 1,
  CURLOPT_POSTFIELDS => $post_data,
  CURLOPT_HTTPHEADER => array(
    //"Authorization: Bearer $TOKEN",
    "Content-Type: multipart/form-data; boundary=" . $delimiter,
    "Content-Length: " . strlen($post_data)

  ),

  
));


//
$response = curl_exec($curl);

$info = curl_getinfo($curl);
//echo "code: ${info['http_code']}";

//print_r($info['request_header']);

var_dump($response);
$err = curl_error($curl);

echo "error";
var_dump($err);
curl_close($curl);




function build_data_files($boundary, $fields, $files){
    $data = '';
    $eol = "\r\n";

    $delimiter = '-------------' . $boundary;

    foreach ($fields as $name => $content) {
        $data .= "--" . $delimiter . $eol
            . 'Content-Disposition: form-data; name="' . $name . "\"".$eol.$eol
            . $content . $eol;
    }


    foreach ($files as $name => $content) {
        $data .= "--" . $delimiter . $eol
            . 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $name . '"' . $eol
            //. 'Content-Type: image/png'.$eol
            . 'Content-Transfer-Encoding: binary'.$eol
            ;

        $data .= $eol;
        $data .= $content . $eol;
    }
    $data .= "--" . $delimiter . "--".$eol;


    return $data;
}


see examples:
https://gist.github.com/iansltx/a6ed41d19852adf2e496
@jaschaio
Copy link
Copy Markdown

I love you. Tried a lot, this finally worked like I needed it.

@chmureck
Copy link
Copy Markdown

Thanks for that, was very useful.
There is a small typo near the beginning:
$url_data = http_build_query($data);
should be
$url_data = http_build_query($fields);

@SoLoGHoST
Copy link
Copy Markdown

Where is $url_data even used at? It seems that you have variables being generated that aren't even used.

@aliosmanyuksel
Copy link
Copy Markdown

$filenames = array("/tmp/1.jpg", "/tmp/2.png");; ---> false
$filenames = array("/tmp/1.jpg", "/tmp/2.png"); ----> true

@GennadiyBilyk
Copy link
Copy Markdown

Thanks a lot

@inspiration-unlimited
Copy link
Copy Markdown

It works! Thank you, man

@systemerrorhy
Copy link
Copy Markdown

can someone explain to me the line: $ fields = array ("f1" => "value1", "another_field2" => "anothervalue");
Is it mandatory to have or different web?

@systemerrorhy
Copy link
Copy Markdown

good

@gangareddy-interakt
Copy link
Copy Markdown

Thanks

@rodesmola
Copy link
Copy Markdown

Nice one, thank you!!

@robtimus
Copy link
Copy Markdown

I found this when searching for a streaming multipart/form-data solution for cURL. Because I couldn't find any I wrote my own: https://packagist.org/packages/robtimus/multipart. This works like the above code but doesn't put everything in memory; it uses cURLs read function instead.

@faai5200
Copy link
Copy Markdown

$filenames = array("/tmp/1.jpg", "/tmp/2.png");; ---> false
$filenames = array("/tmp/1.jpg", "/tmp/2.png"); ----> true

Not an issue bro :)

@jef531
Copy link
Copy Markdown

jef531 commented Apr 6, 2020

Very nice! Thanks,

@dilshad112
Copy link
Copy Markdown

Its work . awesome

@harrisonhenri
Copy link
Copy Markdown

Very nice! You save my life!

@shawnchong
Copy link
Copy Markdown

shawnchong commented Jul 26, 2020

Holy crap, it WORKS and is easily customizable, thanks man.

@ElyVega
Copy link
Copy Markdown

ElyVega commented Oct 21, 2020

Thanks a lot! Works like a charm

@defalt4
Copy link
Copy Markdown

defalt4 commented Feb 9, 2021

Thanks, it helps me alot!

@RatanaKH
Copy link
Copy Markdown

Nice, It works very well!

@tiagoa
Copy link
Copy Markdown

tiagoa commented Sep 28, 2021

Thanks a lot!

@jez321
Copy link
Copy Markdown

jez321 commented Feb 12, 2022

Probably a silly question but what's the reason we need to build the multipart data manually, is it not possible to have curl handle it e.g. https://stackoverflow.com/a/11825645

@luowencai
Copy link
Copy Markdown

Thanks a lot!

@MandelaMan
Copy link
Copy Markdown

Bless you whoever you are!

@Hmerman6006
Copy link
Copy Markdown

Probably a silly question but what's the reason we need to build the multipart data manually, is it not possible to have curl handle it e.g. https://stackoverflow.com/a/11825645

@jez321 you are correct. Thanks for sharing. Struggled for hours before reading your comment and following the link. After a few additional tests I noticed the curl api adds the headers for you, but only if your CURLOPT_POSTFIELDS is a single dimensional array and that you have no raw byte fields in the post packet.

@Roboxkin
Copy link
Copy Markdown

It didn't work for me, I went through a lot of options.
I tried to send a picture, but without success. Probably the code is no longer working.

@ipehimanshu
Copy link
Copy Markdown

Hello

if data has multi dimensional then it not working,

does anyone has solution ?

Thank you

@Xelone28
Copy link
Copy Markdown

Xelone28 commented Feb 5, 2024

Works great thanks !

@oulina
Copy link
Copy Markdown

oulina commented Feb 10, 2024

Thank you very much!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment