日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

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

發布時間:2023/12/19 php 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 磁盘io php,PHP CURL如何处理上传内存中文件,避免磁盘IO开销 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

普通的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开销的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。