Skip to content

Instantly share code, notes, and snippets.

@maxivak
Last active April 4, 2024 10:07
Show Gist options
  • Star 86 You must be signed in to star a gist
  • Fork 22 You must be signed in to fork a gist
  • Save maxivak/18fcac476a2f4ea02e5f80b303811d5f to your computer and use it in GitHub Desktop.
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

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

@chmureck
Copy link

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

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

@aliosmanyuksel
Copy link

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

@GennadiyBilyk
Copy link

Thanks a lot

@inspiration-unlimited
Copy link

It works! Thank you, man

@systemerrorhy
Copy link

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

good

@gangareddy-interakt
Copy link

Thanks

@rodesmola
Copy link

Nice one, thank you!!

@robtimus
Copy link

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

$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

jef531 commented Apr 6, 2020

Very nice! Thanks,

@dilshad112
Copy link

Its work . awesome

@harrisonhenri
Copy link

Very nice! You save my life!

@shawnchong
Copy link

shawnchong commented Jul 26, 2020

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

@ElyVega
Copy link

ElyVega commented Oct 21, 2020

Thanks a lot! Works like a charm

@defalt4
Copy link

defalt4 commented Feb 9, 2021

Thanks, it helps me alot!

@RatanaKH
Copy link

Nice, It works very well!

@tiagoa
Copy link

tiagoa commented Sep 28, 2021

Thanks a lot!

@jez321
Copy link

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

Thanks a lot!

@MandelaMan
Copy link

Bless you whoever you are!

@Hmerman6006
Copy link

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

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

Hello

if data has multi dimensional then it not working,

does anyone has solution ?

Thank you

@Xelone28
Copy link

Xelone28 commented Feb 5, 2024

Works great thanks !

@oulina
Copy link

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