3

I know I can use this syntaxt to send a file using php, post and curl.

$post = array(
    "file_box"=>"@/path/to/myfile.jpg",
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post); 

How can I take a string, build a temp file and send it using the exact same syntax ?

Update: I would prefer using tmpfile() or php://memory so I don't have to handle file creation.

johnlemon
  • 20,761
  • 42
  • 119
  • 178
  • 2
    duplicate of this question: [POST a file string using cURL in PHP?](http://stackoverflow.com/questions/3085990/post-a-file-string-using-curl-in-php) (you will find your answer there) – Lepidosteus May 27 '11 at 09:03
  • Not a real answer there. @emil gave a great solution so far. – johnlemon May 27 '11 at 09:05
  • Erm, yes it is a real answer to send a file through curl when you have its content in a string. Tatu's answer is a different solution that involves temporary files (so you're not sending a string as file, you are sending an actual file). – Lepidosteus May 27 '11 at 09:07
  • @johnlemon: You asked too early, the answer is here: [PHP create random tmp file and get its full path](https://stackoverflow.com/q/16487099/367456) - at least for the tmpfile() part and how to create one from string and obtain the path to it then so you can use it in the (now defunct) @ syntax. – hakre Jul 12 '23 at 09:42

4 Answers4

15

You can create a file using tempnam in your temp directory:

$string = 'random string';

//Save string into temp file
$file = tempnam(sys_get_temp_dir(), 'POST');
file_put_contents($file, $string);

//Post file
$post = array(
    "file_box"=>'@'.$file,
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

//do your cURL work here...

//Remove the file
unlink($file);
Emil Vikström
  • 90,431
  • 16
  • 141
  • 175
1

Since PHP 8.1 there's also CURLStringFile which would allow you to send it without the temporary file:

$txt = 'test content';
$file = new \CURLStringFile($txt, 'filename.txt', 'text/plain');

$ch = curl_init('https://example.com/upload');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $file]);
curl_exec($ch);
manavo
  • 1,839
  • 2
  • 14
  • 17
  • Technically not the @ syntax op asks about. Why not consider to move the answer here: https://stackoverflow.com/q/3085990/367456 ? It looks like a better fit for this reference to me. (you can ping me there so that I can move my +1 there, too). – hakre Jul 12 '23 at 09:32
0

You can create a temporary file using file_put_contents, just make sure that the target directory is writable.

$path = '/path/to/myfile.txt';    
file_put_contents($myData, $path);

$post = array(
    "file_box"=>"@".$path,
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

# Delete the file if you don't need it anymore
unlink($path);
Tatu Ulmanen
  • 123,288
  • 34
  • 187
  • 185
0

From http://php.net/manual/en/class.curlfile.php#115161

function curl_custom_postfields($ch, array $assoc = array(), array $files = array()) {
    
             // invalid characters for "name" and "filename"
             static $disallow = array("\0", "\"", "\r", "\n");

             // build normal parameters
             foreach ($assoc as $k => $v) {
                 $k = str_replace($disallow, "_", $k);
                 $body[] = implode("\r\n", array(
                     "Content-Disposition: form-data; name=\"{$k}\"",
                     "",
                     filter_var($v),
                 ));
             }

             // build file parameters
             foreach ($files as $k => $v) {
                 switch (true) {
                     case false === $v = realpath(filter_var($v)):
                     case !is_file($v):
                     case !is_readable($v):
                         continue; // or return false, throw new InvalidArgumentException
                 }
                 $data = file_get_contents($v);
                 $v = call_user_func("end", explode(DIRECTORY_SEPARATOR, $v));
                 $k = str_replace($disallow, "_", $k);
                 $v = str_replace($disallow, "_", $v);
                 $body[] = implode("\r\n", array(
                     "Content-Disposition: form-data; name=\"{$k}\"; filename=\"{$v}\"",
                     "Content-Type: image/jpeg",
                     "",
                     $data,
                 ));
             }

             // generate safe boundary
             do {
                 $boundary = "---------------------" . md5(mt_rand() . microtime());
             } while (preg_grep("/{$boundary}/", $body));

             // add boundary for each parameters
             array_walk($body, function (&$part) use ($boundary) {
                 $part = "--{$boundary}\r\n{$part}";
             });

             // add final boundary
             $body[] = "--{$boundary}--";
             $body[] = "";

             // set options
             return @curl_setopt_array($ch, array(
                 CURLOPT_POST       => true,
                 CURLOPT_POSTFIELDS => implode("\r\n", $body),
                 CURLOPT_HTTPHEADER => array(
                     "Expect: 100-continue",
                     "Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type
                 ),
             ));
         }

$array1=array('other_post_field'=>'value');
$array2=array('file'=>'document_content_string');
$ch = curl_init();       
curl_setopt($ch, CURLOPT_URL,$url);
curl_custom_postfields($ch,$array1,$array2);//above custom function
$output=curl_exec($ch);
close($ch);
v0if
  • 1
  • 1