简体   繁体   English

使用cURL执行流(逐行)通过POST使用MULTIPART / FORM-DATA进行文件上传

[英]Using cURL to do a stream (line by line) FILE UPLOAD via POST with MULTIPART/FORM-DATA

I want to upload a file to a PHP form on a remote server with a certain URL. 我想将文件上传到具有特定URL的远程服务器上的PHP表单。 The upload form is a file upload form ( Multipart/form-data ), and my script should take a local file, and send it to that form. 上传表单是一个文件上传表单( Multipart/form-data ),我的脚本应该采用本地文件,并将其发送到该表单。

The files are somewhat large, but the form file size limit is 1GB, which is no problem. 文件有点大,但表单文件大小限制为1GB,这没问题。 But what is more pressing is that, due to some circumstances, I have to send the file as a stream! 但更紧迫的是,由于某些情况, 我必须将文件作为流发送!

This means having the file read line by line and then somehow upload it without creating a temporary file to assign via CURLOPTS_POSTFILDS . 这意味着逐行读取文件,然后以某种方式上传它,而不创建通过CURLOPTS_POSTFILDS分配的临时文件。

So in short: 简而言之:

  • I need to use the CURLOPTS_READFUNCTION (I think) to get the contents of the file line by line 我需要使用CURLOPTS_READFUNCTION (我认为) CURLOPTS_READFUNCTION获取文件的内容
  • the method has to be POST 该方法必须是POST
  • this has to simulate a regular file upload on the remote server upload form (so I guess I'd need some sort of a dummy filename for that) 这必须模拟远程服务器上传表单上的常规文件上传(所以我想我需要某种虚拟文件名)

I have tried a lot of ways to do this but I have failed. 我已经尝试了很多方法来做到这一点,但我失败了。 I am very new to cURL , I have tried a lot of info from other StackOverflow questions and other forums to no avail. 我是cURL新手,我已尝试过其他StackOverflow问题和其他论坛的大量信息无济于事。

I have come to the conclusion that it might not be possible, but as I said, I have little idea of what I'm doing so I need some info or guidelines from someone more experienced. 我得出的结论是,这可能是不可能的,但正如我所说,我对我正在做的事情一无所知所以我需要一些更有经验的人的信息或指导。 So far I think that CURLOPT_INFILE and CURLOPT_READFUNCTION are only working with PUT method, but I have to use POST . 到目前为止,我认为CURLOPT_INFILECURLOPT_READFUNCTION仅适用于PUT方法,但我必须使用POST

Sorry for the long question, I hope it makes sense. 很抱歉这个问题很长,我希望这是有道理的。 And thanks in advance for any help or info. 并提前感谢任何帮助或信息。

EDIT 编辑

Here is some code as suggested: 这是一些建议的代码:

$fh = fopen('php://memory','rw');
fwrite( $fh, $content); //maybe write the contents to memory here?
rewind($fh);


$options = array(
    CURLOPT_RETURNTRANSFER  => true
    ,CURLOPT_SSL_VERIFYPEER => false
    ,CURLOPT_SSL_VERIFYHOST => 1
    ,CURLOPT_FOLLOWLOCATION => 0
    ,CURLOPT_HTTPHEADER     => array(
        'Content-type: multipart/form-data'
    )
    ,CURLOPT_INFILE         => $fh //I want to read the contents from this file
    ,CURLOPT_INFILESIZE     => sizeof($content)
);
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, 'remote_form_url_here');
    curl_setopt ($ch, CURLOPT_POST, true);
    $post = array(
         'userfile' => '@i_do_not_have_a_file_to_put_here;filename=myfile.txt'
    );
    curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);
    curl_setopt_array ($ch, $options);


    //have the reading occur line by line when making the infile
    curl_setopt($ch, CURLOPT_READFUNCTION, function($ch, $fd, $length) use ($fh) {
    $line = fgets($fh);
    if ($line !== false) return $line; else return false;
    });


    $response = curl_exec($ch);

    echo $response;
    fclose($fh);

This code is mostly assembled from answers found around, but the parts that use the file handler do not seem to fit. 这段代码主要是根据周围的答案组装而成,但使用文件处理程序的部分似乎不合适。 I want to use a file handler, but it seems that if there is no way to confuse the form into thinking that the contents are a file and to pass some random file name. 我想使用文件处理程序,但似乎没有办法将表单混淆为认为内容是文件并传递一些随机文件名。

This code does not even work (won't get to post the form at all), or some variations of it even show forbidden as a result. 此代码甚至不起作用(根本不会发布表单),或者它的某些变体甚至显示为禁止。

Just for reference this is the test form I'm using to emulate the real situation i'm in until i make it work (don't want to send a ton of requests to the real server): 仅供参考,这是我用来模拟我所处的实际情况的测试表,直到我使其工作(不想向真实服务器发送大量请求):

<form enctype="multipart/form-data" action="up.php" method="POST">


                Send this file: <input name="userfile" type="file" />
                    <input type="submit" value="Send File" />
            </form> 

And this is the behind code: 这是背后的代码:

$target_path = "./ups/";

$target_path = $target_path . basename( $_FILES['userfile']['name']); 

if(move_uploaded_file($_FILES['userfile']['tmp_name'], $target_path)) {
    echo "The file ".  basename( $_FILES['userfile']['name']). 
    " has been uploaded";
} else{
    echo "There was an error uploading the file, please try again!";
}

var_dump($_FILES['userfile']);

If it works OK in the browser, you may use chrome dev tools. 如果它在浏览器中正常工作,您可以使用chrome dev工具。 On Network Tab, find the post request. 在“网络”选项卡上,找到发布请求。 Right click -> Copy as cURL . 右键单击 - >复制为cURL。

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

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