资讯专栏INFORMATION COLUMN

PHP CURL如何处理上传内存中文件,避免磁盘IO开销

jackwang / 768人阅读

摘要:当然该参数可以通过修改自己构造请求的主体实现任意大小文件的直接内存上传通过上传文件,不管是磁盘文件还是内存中的字符串也好,其实都是基于协议的请求。

普通的CURL上传磁盘文件的方式

发送方 send.php的代码如下:

 "123456",
    "file_contents" => "@$filename;filename=test.txt;type=text/plain",
);
*/
/*
 * 第二种写法,推荐新版本php中使用
 * CURLFile参数解释
 * @$filename 需要上传的文件,建议使用绝对路径
 * @$mimetype: 默认是 application/octet-stream,此处留空
 * @$postname: 接收方$_FILES数组中的文件名,此处为 test.txt
 */
$file = new CURLFile($filename, "", "test.txt");
$post_data = array(
    "extra_info" => "123456",
    "file_contents" => $file,
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$result = curl_exec($ch);
curl_close($ch);
echo $result;

处理上传文件的代码upload.php示例:

";
if(move_uploaded_file($_FILES["file_contents"]["tmp_name"], $uploadfile)) {
    echo "ok!";
} else {
    echo "failed!";
}
//调试信息
var_dump($_FILES);
var_dump($_POST);
利用 PUT 方法上传内存中的文件

有些时候脚本产生的临时小文件,利用普通的上传方式,则需要先把文件写入磁盘,再作为文件上传。产生了额外的开销。最好的办法是直接上传。
重新实现send.php 代码如下:



没有用 php://memory,会报错 Warning: curl_setopt(): cannot represent a stream of type MEMORY as a STDIO FILE* 暂无好的解决方案
处理上传的文件的脚本也需要修改下:



这个方法,适合上传小于2MB的文件,否则还是会生成临时文件。当然该参数可以通过php.ini修改

自己构造请求的主体 实现任意大小文件的直接内存上传

通过CURL 上传文件,不管是磁盘文件还是内存中的字符串也好,其实都是基于HTTP协议的请求。
如果自己构造这段请求,便不再局限于文件的形式了。

 array(
        "name" => "test1.txt",
        "type" => "text/plain",
        "content" => "...this is my file content..."
    ),
    "file2" => array(
        "name" => "test.txt",
        "type" => "text/plain",
        "content" => "... this is my two file"
    ),
);
//后端接受的$_POST的数组值
$postFields = array(
    "myname" => "joe",
);
//@var $data 保存主体的字符串
$data = "";

//先将post的普通数据生成主体字符串
foreach ($postFields as $name => $content) {
    $data .= "--" . $delimiter . "
";
    $data .= "Content-Disposition: form-data; name="" . $name . """;
    //multipart/form-data 不需要urlencode,参见 http:stackoverflow.com/questions/6603928/should-i-url-encode-post-data
    $data .= "

" . $content . "
";
}
//将上传的文件生成主体字符串
foreach ($fileFields as $name => $file) {
    $data .= "--" . $delimiter . "
";
    $data .= "Content-Disposition: form-data; name="" . $name . ""; filename="" . $file["name"] . "" 
";
    $data .= "Content-Type: " . $file["type"] . "

";//多了个文档类型

    $data .= $file["content"] . "
";
}
//主体结束的分隔符
$data .= "--" . $delimiter . "--";

$target_url = "http://localhost/upload.php";
$handle = curl_init($target_url);
curl_setopt($handle, CURLOPT_POST, true);
curl_setopt($handle, CURLOPT_HTTPHEADER , array(
    "Content-Type: multipart/form-data; boundary=" . $delimiter,
    "Content-Length: " . strlen($data))
); 
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($handle);
curl_close($handle);
//echo $result;

这种方式实现稍显复杂,但不需要更改处理上传的代码,跟第一种磁盘文件的方法一样。
其他参考

深入浅出php下的文件上传 提到了一些安全处理的技巧
简述php中curl的使用

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31867.html

相关文章

  • 阿里云服务器 何处网站高并发流量问题?(含教程)

    摘要:阿里云哪个节点服务器好一下看看负载均衡它是对多台云服务器进行流量分发的负载均衡服务,让整个服务器群来处理网站的请求。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。原文流量大的网站如何处理高并发流量问题很多平台一旦做大了,平台的流量就会陡增,同时并发访问的流量也会暴增,原本规划的硬件配置就无法满足当下的流量问题。 那么如何处理好高并发的流量问题呢? 小编将这些分为2个方...

    waterc 评论0 收藏0
  • 入门架构——单机高性能

    摘要:协作方式在高并发场景中,必须要让服务器同时维护大量请求连接,可能是一个服务进程创建另一个进程,也可能是一个服务线程去创建另一个线程,但连接结束后进程或线程就销毁了,这是一个巨大的浪费一个自然的想法就是通过创建一个进程线程池从而达到资源复用, showImg(https://segmentfault.com/img/bVbtgn1?w=313&h=208); 协作方式 在高并发场景中,必...

    UCloud 评论0 收藏0
  • 追寻终极数据库 - 事务/分析混合处系统的交付挑战 (4)(完结篇)

    摘要:评估选项本报告涵盖了为了支持工作负载涵盖运营和分析,查询引擎面临的挑战的细节,这些细节也可以作为访问数据库引擎查询引擎和存储引擎组合以及满足事务运营分析或混合工作负载需求的指南。 评估HTAP选项 本报告涵盖了为了支持工作负载(涵盖OLTP、运营、BI和分析),查询引擎面临的挑战的细节,这些细节也可以作为访问数据库引擎、查询引擎和存储引擎组合以及满足事务、运营、分析或混合工作负载需求的...

    nanchen2251 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<