简体   繁体   English

如何使用文件的内容而不是`curl_file_create`函数的文件名?

[英]How to use the content of the file instead of filename for `curl_file_create` function?

The first parameter of the curl_file_create function is the filename. curl_file_create函数的第一个参数是文件名。 Is there a way to directly use the content of the file? 有没有办法直接使用文件的内容?
I do not want to write content in a temporary file and use that filename in the function. 我不想在临时文件中写入内容并在函数中使用该文件名。

More expand: 更多扩展:
I get an image from URL with $image = file_get_contents('http://example.com/image.jpg'); 我使用$image = file_get_contents('http://example.com/image.jpg');从URL获取图像$image = file_get_contents('http://example.com/image.jpg'); function, and so I have a $image variable with binary image content for now, After get it I need to post this image as part of form to another URL instantly without use temporary file on disk. 函数,所以我现在有一个带有二进制图像内容的$image变量,在得到它之后我需要立即将这个图像作为表单的一部分发布到另一个URL而不使用磁盘上的临时文件。

to anyone thinking about doing this: it's almost certainly not worth the hassle. 任何想到这样做的人:这几乎肯定不值得麻烦。 it's possible, sure, but you'd almost certainly want to use the tmpfile() trick instead, for example if you have a variable called $file_content that you want to upload as a file, but you don't have a file, do 这是可能的,当然,但你几乎肯定想要使用tmpfile()技巧,例如,如果你有一个名为$file_content的变量,你想要上传为文件,但你没有文件,那么

<?php
$file_content = "the content of the *file* i want to upload, which does not exist on disk";
$file_name = "example.bin";
$tmph = tmpfile(); // will create a file in the appropriate temp folder when an unique filename
fwrite($tmph, $file_content);
$tmpf = stream_get_meta_data($tmph)['uri'];
$ch = curl_init('http://target_url/');
curl_setopt_array($ch, array(
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => array(
        'file' => new CURLFile($tmpf, 'application/octet-stream', $file_name)
    )
));
curl_exec($ch);
fclose($tmph); // thanks to tmpfile() magic, the file is automatically deleted when fclosed()'d
unset($tmph, $tmpf); // unset() is not needed, but this is the end of the tmpfile()-trick.

.. and with a bit of luck, as long as the upload is quick and we don't call fflush($tmph);, the file may never touch the actual disk anyway, it will just be created in the IO cache, scheduled to be written to disk later, then deleted (from the io cache) - also this code is protected by PHP's garbage collector, if there's an uncaught exception/error in the code which stops execution, PHP's garbage collector will delete the file for us.. ..并且有点运气,只要上传很快而且我们不调用fflush($ tmph);,该文件可能永远不会触及实际磁盘,它只会在IO缓存中创建,预定以后写入磁盘,然后删除(从io缓存) - 此代码也受PHP的垃圾收集器保护,如果代码中有未捕获的异常/错误停止执行,PHP的垃圾收集器将为我们删除该文件。 。

However, here's how to actually upload a file in the Multipart/form-data -format without having nor creating an on-disk file, by creating the Multipart/form-data -request with userland PHP code: 但是,这里是如何通过使用userland PHP代码创建Multipart/form-data -request,在没有创建磁盘文件的情况下实际上传Multipart/form-data -format中的文件:

usage example: 用法示例:

<?php

// normal php-way: 
$ch = curl_init();
curl_setopt_array($ch, array(
    CURLOPT_URL=>'https://example.com/',
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => array(
        'sample_variable' => 'anything',
        'file' => new CURLFile("path/to/file.txt")
    )
));
curl_exec($ch);
curl_close($ch);
// shitty_multipart-way: 
$post_data = array();
$tmp = new shitty_multipart_variable();
$tmp->post_name = 'sample_variable';
$tmp->content = 'anything';
$post_data[] = $tmp;
$tmp = new shitty_multipart_file();
$tmp->post_name = 'file';
$tmp->post_file_name = "file.ext";
$tmp->content = 'contents of file.ext';
$post_data[] = $tmp;
$content_type_header="";
$post_body=shitty_multipart_form_data_generator($post_data,$content_type_header);
$ch = curl_init();
curl_setopt_array($ch, array(
    CURLOPT_URL=>'https://example.com/',
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => $post_body,
    CURLOPT_HTTPHEADER=>array(
        $content_type_header
    )
));
curl_exec($ch);
curl_close($ch);

implementation: 执行:

class shitty_multipart_file
{
    public $post_name = "";
    public $file_name = "";
    public $content_type = "application/octet-stream";
    public $content = "";
    public $additional_headers = [];
}
class shitty_multipart_variable
{
    public $post_name = "";
    public $content = "";
    public $additional_headers = [];
}
function shitty_multipart_form_data_generator(array $postfields, string &$out_content_type_header): string
{
    // Content-Type: multipart/form-data; boundary=------------------------7b5b9abe8c56fd67
    // same boundary format as used by curl
    $boundary = "------------------------" . strtolower(bin2hex(random_bytes(8)));
    $out_content_type_header = 'Content-Type: multipart/form-data; boundary=' . $boundary;
    $body = "";
    foreach ($postfields as $unused => $post) {
        $body .= $boundary . "\r\n";
        if (is_a($post, 'shitty_multipart_variable')) {
            $body .= "Content-Disposition: form-data; name=\"{$post->post_name}\"\r\n";
            foreach ($post->additional_headers as $header) {
                $body .= $header . "\r\n";
            }
            $body .= "\r\n";
            $body .= $post->content . "\r\n";
        } elseif (is_a($post, 'shitty_multipart_file')) {
            $body .= "Content-Disposition: form-data; name=\"{$post->post_name}\"; filename=\"{$post->file_name}\"\r\n";
            $body .= "Content-Type: " . $post->content_type . "\r\n";
            foreach ($post->additional_headers as $header) {
                $body .= $header . "\r\n";
            }
            $body .= "\r\n";
            $body .= $post->content . "\r\n";
        } else {
            throw new \InvalidArgumentException("postfields key {$unused} is not an instance of shitty_multipart_variable NOR an instance of shitty_multipart_file!");
        }
    }
    $body .= $boundary . "--\r\n";
    return $body;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM