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

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

$target_url = "http://localhost/upload.php";

$filename = realpath("test.txt");

/*

* 第一种写法,但是在5.5以上版本不推荐使用

* @$filename 是文件路径,必须有

* filename=test.txt 是接收方收到的文件名,为空时 则取 filename 文件路径中的 basename部分

* type=text/plain 文档类型,可以为空

*/

/*

$post_data = array(

'extra_info' => '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示例:

$upload_dir = realpath('./') . '/';

$uploadfile = $upload_dir . basename($_FILES['file_contents']['name']);

echo '

<

pre>';

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://temp 会在内存量达到预定义的限制后(默认是 2MB)存入临时文件中。

*/

$fh = fopen('php://temp', 'rw+');

$string = 'test';

fwrite($fh, $string);

rewind($fh);

$ch = curl_init('http://localhost/putfile.php');

curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);

curl_setopt($ch, CURLOPT_PUT, true);

curl_setopt($ch, CURLOPT_INFILE, $fh);

curl_setopt($ch, CURLOPT_INFILESIZE, strlen($string));

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);

curl_close($ch);

fclose($fh);

没有用 php://memory,会报错 Warning: curl_setopt(): cannot represent a stream of type MEMORY as a STDIO FILE* 暂无好的解决方案

处理上传的文件的脚本也需要修改下:

//修改自PHP手册中的代码

$putdata = fopen("php://input", "r");

/* Open a file for writing */

$fp = fopen("myputfile.txt", "w");

/* Read the data 1 KB at a time

and write to the file */

while ($data = fread($putdata, 1024))

fwrite($fp, $data);

/* Close the streams */

fclose($fp);

fclose($putdata);

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

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

通过CURL 上传文件,不管是磁盘文件还是内存中的字符串也好,其实都是基于HTTP协议的请求。

如果自己构造这段请求,便不再局限于文件的形式了。

/**

* 参考rfc1867协议 第6部分的 examples 中的格式 : http://www.ietf.org/rfc/rfc1867.txt

* 如下:第一行是header 中的(省略了其他header),其他部分是主体部分

Content-type: multipart/form-data, boundary=AaB03x

--AaB03x

content-disposition: form-data; name="field1"

Joe Blow

--AaB03x

content-disposition: form-data; name="pics"; filename="file1.txt"

Content-Type: text/plain

... contents of file1.txt ...

--AaB03x--

* 或

Content-type: multipart/form-data, boundary=AaB03x

--AaB03x

content-disposition: form-data; name="field1"

Joe Blow

--AaB03x

content-disposition: form-data; name="pics"

Content-type: multipart/mixed, boundary=BbC04y

--BbC04y

Content-disposition: attachment; filename="file1.txt"

Content-Type: text/plain

... contents of file1.txt ...

--BbC04y

Content-disposition: attachment; filename="file2.gif"

Content-type: image/gif

Content-Transfer-Encoding: binary

...contents of file2.gif...

--BbC04y--

--AaB03x--

* CURL POST,对 CURLOPT_POSTFIELDS 的设置,倘若是字符串可以解释为主体部分

*/

//生成分隔符

$delimiter = '-------------' . uniqid();

//需要上传的文件数组

$fileFields = array(

'file1' => 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 . "\r\n";

$data .= 'Content-Disposition: form-data; name="' . $name . '"';

//multipart/form-data 不需要urlencode,参见 http:stackoverflow.com/questions/6603928/should-i-url-encode-post-data

$data .= "\r\n\r\n" . $content . "\r\n";

}

//将上传的文件生成主体字符串

foreach ($fileFields as $name => $file) {

$data .= "--" . $delimiter . "\r\n";

$data .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $file['name'] . "\" \r\n";

$data .= 'Content-Type: ' . $file['type'] . "\r\n\r\n";//多了个文档类型

$data .= $file['content'] . "\r\n";

}

//主体结束的分隔符

$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;

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

其他参考

磁盘io php,PHP CURL如何处理上传内存中文件,避免磁盘IO开销相关推荐

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

    普通的CURL上传磁盘文件的方式 发送方 send.php的代码如下: <?php $target_url = "http://localhost/upload.php"; ...

  2. linux下上传系统中文件到gitHub

    linux下上传系统中文件到gitHub 一: 1系统下生成公钥 #ssh-keygen 一路回车即可 2对公钥进行复制 #cat .shh/id_rsa.pub 3将公钥复制到github中 首先要 ...

  3. php上传 io err,【Dz上传附件】解决Discuz Server(IO)Error问题

    [Dz上传附件]解决Discuz Server(IO)Error问题 2018-12-17 Discuz 上传文件时会碰到Discuz Server(IO)Error错误了,这个小编排查了许久没找到问 ...

  4. 使用curl下载上传ftp

    curl可以在shell下轻松上传下载ftp上的文件,相比ftp命令更具有优势,因为它能在单命令条件下,下载或者上传一个ftp文件,甚至可以删除文件. 下面看实例: 列出ftp服务器上的目录列表: c ...

  5. curl post json_curl 模拟 GETPOST 请求,以及 curl post 上传文件

    curl 模拟 GETPOST 请求,以及 curl post 上传文件 一般情况下,我们调试数据接口,都会使用一个 postman 的工具,但是这个工具还是有点大了.事实上,我们在调试一些小功能的时 ...

  6. linux curl t上传文件,curl 命令行上传文件

    现在nginx大行其道,一般在机器上装个nginx 简答配置下就可以做upload用了.主要需求是开发那边需要运维这边投递一些app_log和一些history log.下面讲解下直接用curl命令上 ...

  7. 使用curl 命令上传下载FTP

    CURL命令 1.列出ftp服务器上的目录列表: curl ftp://www.xxx.com/ --user name:passwd curl ftp://www.xxx.com/ –u name: ...

  8. curl 模拟 GET\POST 请求,以及 curl post 上传文件

    curl 模拟 GET\POST 请求,以及 curl post 上传文件 一般情况下,我们调试数据接口,都会使用一个 postman 的工具,但是这个工具还是有点大了.事实上,我们在调试一些小功能的 ...

  9. (私有云)客户给的VMware镜像磁盘如何制作成自定义镜像上传至openstack镜像服务器供客户使用

    (私有云)客户给的VMware镜像磁盘如何制作成自定义镜像上传至openstack镜像服务器供客户使用 目录 1.准备工作 2.修改域xml配置文件以及是否缩容 3.在镜像更新服务器上启动这个自定义镜 ...

最新文章

  1. 胡渊鸣的「太极图形」又融了5000万美元,下一步:3D内容创作平台
  2. 4、(日期和时间类型)DTAETIME、TIMESTAMP、DATE、TIME、YEAR
  3. html5元素拖动 (转载黑桐)
  4. Linux下使用crontab命令以及Python脚本实现自动签到
  5. 有人说,如果有条件一定要远离穷人,你赞成吗?
  6. Codeforces Round #665 (Div. 2)
  7. 一个c++ 2d图形引擎 AGG
  8. 浅谈常见的NoSQL技术方案和选型
  9. 15_采用Pull解析器解析和生成XML内容
  10. 大班线描机器人_大班美术教案机器人
  11. 手把手玩转win8开发系列课程(9)
  12. Python的中文处理
  13. Mikrotik ROS软路由设置上网方式(三)
  14. MP4Box常用命令
  15. Tomcat启动报Exception in thread “main“ java.lang.UnsatisfiedLinkError: no secure-tomcat in java.library
  16. Photoshop基本使用
  17. MATLAB之心形图绘制
  18. 从头开始绘制一个圆锥体
  19. 网络安全笔记--文件上传1(文件上传基础、常见后端验证、黑名单、白名单、后端绕过方式)
  20. 3. 自建DNS(bind9)

热门文章

  1. SAP Spartacus 用户登录成功后,Access Token 持久化到浏览器 local storage 的执行原理
  2. 漫谈SAP产品里页面上的Checkbox设计与实现系列之一
  3. Java 8里的Predicate学习笔记
  4. 在SAP CDS view上添加扩展字段后激活,背后的实现原理
  5. 一个能极大提高生产率的Chrome新建标签页扩展
  6. OData debug - Java client - why my batch request fails
  7. smart field demo1 - how does system know currency needs to be rendered
  8. 如何通过Fiori后台调试的方式找到gateway系统的ID
  9. Cloud Connector的普通版本和Portable版本的区别
  10. Enterprise search result view column显示technical name