├── tests
├── mock-server
│ ├── timeout.php
│ ├── ok.php
│ └── redirect.php
├── socks5-server
│ ├── go.mod
│ ├── go.sum
│ └── main.go
├── Qiniu
│ └── Tests
│ │ ├── Base64Test.php
│ │ ├── Crc32Test.php
│ │ ├── DownloadTest.php
│ │ ├── FopTest.php
│ │ ├── EtagTest.php
│ │ ├── EntryTest.php
│ │ ├── ConfigTest.php
│ │ ├── ZoneTest.php
│ │ ├── MiddlewareTest.php
│ │ ├── CdnManagerTest.php
│ │ ├── HeaderTest.php
│ │ ├── HttpTest.php
│ │ └── FormUpTest.php
└── bootstrap.php
├── examples
├── php-logo.png
├── qetag.php
├── README.md
├── persistent_fop_init.php
├── upload_mgr_init.php
├── persistent_fop_status.php
├── rs_download_urls.php
├── cdn_timestamp_antileech.php
├── get_bucketinfo.php
├── rs_buckets.php
├── rtc
│ ├── rtc_deleteApp.php
│ ├── rtc_getApp.php
│ ├── rtc_rooms_stopMerge.php
│ ├── rtc_rooms_listUser.php
│ ├── rtc_rooms_kickUser.php
│ ├── rtc_createApp.php
│ ├── rtc_rooms_listActiveRooms.php
│ ├── rtc_create_roomToken.php
│ ├── rtc_updateApp.php
│ └── README.md
├── sms
│ ├── sms_delete_template.php
│ ├── sms_delete_signature.php
│ ├── sms_query_single_template.php
│ ├── sms_query_single_signature.php
│ ├── sms_query_template.php
│ ├── sms_query_signature.php
│ ├── sms_send_message.php
│ ├── sms_create_signature.php
│ ├── sms_edit_signature.php
│ ├── sms_edit_template.php
│ ├── sms_create_template.php
│ ├── sms_query_send_sms.php
│ └── README.md
├── rs_prefetch.php
├── get_bucketQuota.php
├── prefop.php
├── delete_bucket.php
├── get_corsRules.php
├── get_bucketEvents.php
├── rs_delete.php
├── rs_stat.php
├── rs_bucket_domains.php
├── get_bucketLifecycleRules.php
├── rs_restore.php
├── get_bucketList.php
├── get_bucketinfos.php
├── put_bucketQuota.php
├── rs_delete_after_days.php
├── put_bucketAccessMode.php
├── delete_bucketLifecycleRule.php
├── put_bucketAccessStyleMode.php
├── rs_change_mime.php
├── put_bucketMaxAge.php
├── rs_change_status.php
├── delete_bucketEvent.php
├── rs_batch_delete.php
├── rs_batch_stat.php
├── cdn_get_log_list.php
├── rs_move.php
├── rsf_v2list_bucket.php
├── rs_copy.php
├── rs_change_type.php
├── rs_batch_change_mime.php
├── update_bucketEvent.php
├── cdn_get_flux.php
├── update_bucketLifecycleRule.php
├── upload_simple_file.php
├── put_bucketEvent.php
├── rs_batch_delete_after_days.php
├── put_referAntiLeech.php
├── rs_batch_copy.php
├── upload_and_callback.php
├── cdn_get_bandwidth.php
├── rs_batch_restore_ar.php
├── rs_batch_move.php
├── rsf_list_files.php
├── saveas.php
├── censor_image.php
├── upload_verify_callback.php
├── upload_with_zone.php
├── rs_batch_change_type.php
├── upload_with_qvmzone.php
├── censor_video.php
├── cdn_get_prefetch_list.php
├── rs_fetch.php
├── bucket_lifecycleRule.php
├── rsf_list_bucket.php
├── cdn_get_refresh_list.php
├── upload_and_pfop.php
├── pfop_video_avthumb.php
├── pfop_vframe.php
├── pfop_mkzip.php
├── pfop_watermark.php
├── cdn_refresh_urls_dirs.php
├── rs_asynch_fetch.php
├── image_url_builder.php
├── upload_multi_demos.php
└── upload_tokens.php
├── test-env.sh
├── .gitignore
├── src
└── Qiniu
│ ├── Enum
│ ├── SplitUploadVersion.php
│ └── QiniuEnum.php
│ ├── Http
│ ├── Error.php
│ ├── Middleware
│ │ ├── Middleware.php
│ │ └── RetryDomainsMiddleware.php
│ ├── Request.php
│ ├── Proxy.php
│ ├── RequestOptions.php
│ └── Client.php
│ ├── Zone.php
│ ├── Processing
│ ├── Operation.php
│ └── PersistentFop.php
│ ├── Etag.php
│ └── Storage
│ ├── ArgusManager.php
│ ├── FormUploader.php
│ └── UploadManager.php
├── autoload.php
├── phpunit.xml.dist
├── .github
└── workflows
│ ├── version-check.yml
│ └── test-ci.yml
├── CONTRIBUTING.md
├── codecov.yml
├── LICENSE
├── composer.json
├── .scrutinizer.yml
├── README.md
└── CHANGELOG.md
/tests/mock-server/timeout.php:
--------------------------------------------------------------------------------
1 | assertEquals($a, \Qiniu\base64_urlSafeDecode($b));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # examples
2 |
3 | 这些 examples 旨在帮助你快速了解使用七牛的 SDK。这些 demo 都是可以直接运行的, 但是在运行之前需要填上您自己的参数。
4 |
5 | 比如:
6 |
7 | * `$bucket` 需要填上您想操作的 [bucket名字](https://portal.qiniu.com/kodo/bucket)。
8 | * `$accessKey` 和 `$secretKey` 可以在我们的[管理后台](https://portal.qiniu.com/user/key)找到。
9 | * 在进行`视频转码`, `压缩文件`等异步操作时 需要使用到的队列名称也可以在我们[管理后台](https://portal.qiniu.com/dora/media-gate/pipeline)新建。
10 |
11 |
--------------------------------------------------------------------------------
/tests/socks5-server/go.sum:
--------------------------------------------------------------------------------
1 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
2 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
3 | golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
4 | golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
5 |
--------------------------------------------------------------------------------
/examples/persistent_fop_init.php:
--------------------------------------------------------------------------------
1 | useHTTPS=true;
16 |
17 | // 初始化
18 | $pfop = new PersistentFop($auth, $config);
19 |
--------------------------------------------------------------------------------
/examples/upload_mgr_init.php:
--------------------------------------------------------------------------------
1 | uploadToken($bucket);
17 |
18 | // 构建 UploadManager 对象
19 | $uploadMgr = new UploadManager();
20 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/Crc32Test.php:
--------------------------------------------------------------------------------
1 | assertEquals('1352841281', $b);
15 | }
16 |
17 | public function testFile()
18 | {
19 | $b = \Qiniu\crc32_file(__file__);
20 | $c = \Qiniu\crc32_file(__file__);
21 | $this->assertEquals($c, $b);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/autoload.php:
--------------------------------------------------------------------------------
1 | status($persistentId);
15 | if ($err != null) {
16 | var_dump($err);
17 | } else {
18 | var_dump($ret);
19 | }
20 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | tests
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/tests/socks5-server/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 |
7 | socks5 "github.com/armon/go-socks5"
8 | )
9 |
10 | func main() {
11 | config := socks5.Config{
12 | AuthMethods: []socks5.Authenticator{socks5.UserPassAuthenticator{Credentials: socks5.StaticCredentials{"user": "pass"}}},
13 | Logger: log.New(os.Stderr, "", log.LstdFlags|log.LUTC|log.Lshortfile),
14 | }
15 |
16 | server, err := socks5.New(&config)
17 | if err != nil {
18 | panic(err)
19 | }
20 |
21 | if err = server.ListenAndServe("tcp", "127.0.0.1:8080"); err != nil {
22 | panic(err)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.github/workflows/version-check.yml:
--------------------------------------------------------------------------------
1 | name: PHP SDK Version Check
2 | on:
3 | push:
4 | tags:
5 | - "v[0-9]+.[0-9]+.[0-9]+"
6 | jobs:
7 | linux:
8 | name: Version Check
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout code
12 | uses: actions/checkout@v2
13 | - name: Set env
14 | run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/v}" >> $GITHUB_ENV
15 | - name: Check
16 | run: |
17 | set -e
18 | grep -qF "## ${RELEASE_VERSION}" CHANGELOG.md
19 | grep -qF "const SDK_VER = '${RELEASE_VERSION}';" src/Qiniu/Config.php
20 |
--------------------------------------------------------------------------------
/examples/rs_download_urls.php:
--------------------------------------------------------------------------------
1 | /,一定要带访问协议,也就是 http:// 或者 https://
14 | $baseUrl = 'http://if-pri.qiniudn.com/qiniu.png?imageView2/1/h/500';
15 |
16 | // 对链接进行签名,参考文档:https://developer.qiniu.com/kodo/manual/1656/download-private
17 | $signedUrl = $auth->privateDownloadUrl($baseUrl);
18 |
19 | echo $signedUrl;
20 |
--------------------------------------------------------------------------------
/examples/cdn_timestamp_antileech.php:
--------------------------------------------------------------------------------
1 | bucketInfo($bucket);
21 | if ($err != null) {
22 | var_dump($err);
23 | } else {
24 | var_dump($ret);
25 | }
26 |
--------------------------------------------------------------------------------
/examples/rs_buckets.php:
--------------------------------------------------------------------------------
1 | buckets(true);
21 | if ($err != null) {
22 | var_dump($err);
23 | } else {
24 | var_dump($ret);
25 | }
26 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_deleteApp.php:
--------------------------------------------------------------------------------
1 | deleteApp($appId);
21 | if ($err !== null) {
22 | var_dump($err);
23 | } else {
24 | echo "\n====> Delete $appId Successfully \n";
25 | }
26 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_getApp.php:
--------------------------------------------------------------------------------
1 | getApp($appId);
21 | if ($err !== null) {
22 | var_dump($err);
23 | } else {
24 | echo "\n====> $appId Conf: \n";
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/sms/sms_delete_template.php:
--------------------------------------------------------------------------------
1 | deleteTemplate($template_id);
21 | if ($err !== null) {
22 | var_dump($err);
23 | } else {
24 | echo "\n====> Delete Template $template_id Successfully\n";
25 | }
26 |
--------------------------------------------------------------------------------
/examples/rs_prefetch.php:
--------------------------------------------------------------------------------
1 | prefetch($bucket, $key);
21 | if ($err != null) {
22 | var_dump($err);
23 | } else {
24 | var_dump($ret);
25 | }
26 |
--------------------------------------------------------------------------------
/examples/sms/sms_delete_signature.php:
--------------------------------------------------------------------------------
1 | deleteSignature($signature_id);
21 | if ($err !== null) {
22 | var_dump($err);
23 | } else {
24 | echo "\n====> Delete Signature $signature_id Successfully\n";
25 | }
26 |
--------------------------------------------------------------------------------
/examples/get_bucketQuota.php:
--------------------------------------------------------------------------------
1 | getBucketQuota($bucket);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/prefop.php:
--------------------------------------------------------------------------------
1 | useHTTPS=true;
15 |
16 | $pfop = new PersistentFop($auth, $config);
17 |
18 | $id = "z2.01z201c4oyre6q1hgy00murnel0002nh";
19 |
20 | // 查询持久化处理的进度和状态
21 | list($ret, $err) = $pfop->status($id);
22 | echo "\n====> pfop avthumb status: \n";
23 | if ($err != null) {
24 | var_dump($err);
25 | } else {
26 | var_dump($ret);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/delete_bucket.php:
--------------------------------------------------------------------------------
1 | deleteBucket($bucket);
23 | if ($err != null) {
24 | var_dump($err);
25 | } else {
26 | var_dump($ret);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/sms/sms_query_single_template.php:
--------------------------------------------------------------------------------
1 | querySingleTemplate($template_id);
21 | echo "\n====> query single template result: \n";
22 | if ($err !== null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/get_corsRules.php:
--------------------------------------------------------------------------------
1 | getCorsRules($bucket);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/sms/sms_query_single_signature.php:
--------------------------------------------------------------------------------
1 | checkSingleSignature($signature_id);
21 | echo "\n====> query single signature result: \n";
22 | if ($err !== null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/get_bucketEvents.php:
--------------------------------------------------------------------------------
1 | getBucketEvents($bucket);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/rs_delete.php:
--------------------------------------------------------------------------------
1 | delete($bucket, $key);
23 | if ($err != null) {
24 | var_dump($err);
25 | } else {
26 | var_dump($ret);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/rs_stat.php:
--------------------------------------------------------------------------------
1 | stat($bucket, $key);
24 | if ($err != null) {
25 | var_dump($err);
26 | } else {
27 | var_dump($ret);
28 | }
29 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_rooms_stopMerge.php:
--------------------------------------------------------------------------------
1 | stopMerge($appId, $roomName);
24 | if ($err !== null) {
25 | var_dump($err);
26 | } else {
27 | echo "\n====> Stop Merge Successfully \n";
28 | }
29 |
--------------------------------------------------------------------------------
/examples/rs_bucket_domains.php:
--------------------------------------------------------------------------------
1 | domains($bucket);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_rooms_listUser.php:
--------------------------------------------------------------------------------
1 | listUser($appId, $roomName);
24 | if ($err !== null) {
25 | var_dump($err);
26 | } else {
27 | echo "\n====> User List: \n";
28 | var_dump($ret);
29 | }
30 |
--------------------------------------------------------------------------------
/examples/get_bucketLifecycleRules.php:
--------------------------------------------------------------------------------
1 | getBucketLifecycleRules($bucket);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/rs_restore.php:
--------------------------------------------------------------------------------
1 | restoreAr($bucket, $key, 1);
24 | if ($err != null) {
25 | var_dump($err);
26 | } else {
27 | var_dump($ret);
28 | }
29 |
--------------------------------------------------------------------------------
/examples/get_bucketList.php:
--------------------------------------------------------------------------------
1 | listbuckets($region);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/get_bucketinfos.php:
--------------------------------------------------------------------------------
1 | bucketInfos($region);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/put_bucketQuota.php:
--------------------------------------------------------------------------------
1 | putBucketQuota($bucket, $size, $count);
25 | if ($err != null) {
26 | var_dump($err);
27 | } else {
28 | var_dump($ret);
29 | }
30 |
--------------------------------------------------------------------------------
/examples/rs_delete_after_days.php:
--------------------------------------------------------------------------------
1 | deleteAfterDays($bucket, $key, $days);
22 | if ($err != null) {
23 | var_dump($err);
24 | } else {
25 | var_dump($ret);
26 | }
27 |
--------------------------------------------------------------------------------
/src/Qiniu/Http/Error.php:
--------------------------------------------------------------------------------
1 |
7 | * {"error" : "detailed error message"}
8 | *
9 | */
10 | final class Error
11 | {
12 | private $url;
13 | /**
14 | * @var Response
15 | */
16 | private $response;
17 |
18 | public function __construct($url, $response)
19 | {
20 | $this->url = $url;
21 | $this->response = $response;
22 | }
23 |
24 | public function code()
25 | {
26 | return $this->response->statusCode;
27 | }
28 |
29 | public function getResponse()
30 | {
31 | return $this->response;
32 | }
33 |
34 | public function message()
35 | {
36 | return $this->response->error;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/examples/put_bucketAccessMode.php:
--------------------------------------------------------------------------------
1 | putBucketAccessMode($bucket, $private);
23 | if ($err != null) {
24 | var_dump($err);
25 | } else {
26 | var_dump($ret);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/delete_bucketLifecycleRule.php:
--------------------------------------------------------------------------------
1 | deleteBucketLifecycleRule($bucket, $name);
23 | if ($err != null) {
24 | var_dump($err);
25 | } else {
26 | var_dump($ret);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/put_bucketAccessStyleMode.php:
--------------------------------------------------------------------------------
1 | putBucketAccessStyleMode($bucket, $mode);
23 | if ($err != null) {
24 | var_dump($err);
25 | } else {
26 | var_dump($ret);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/rs_change_mime.php:
--------------------------------------------------------------------------------
1 | changeMime($bucket, $key, $newMime);
25 | if ($err != null) {
26 | var_dump($err);
27 | } else {
28 | var_dump($ret);
29 | }
30 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_rooms_kickUser.php:
--------------------------------------------------------------------------------
1 | kickUser($appId, $roomName, $userId);
27 | if ($err !== null) {
28 | var_dump($err);
29 | } else {
30 | echo "\n====> Kick User $userId Successfully \n";
31 | }
32 |
--------------------------------------------------------------------------------
/examples/put_bucketMaxAge.php:
--------------------------------------------------------------------------------
1 | putBucketMaxAge($bucket, $maxAge);
23 | if ($err != null) {
24 | var_dump($err);
25 | } else {
26 | var_dump($ret);
27 | }
28 |
--------------------------------------------------------------------------------
/examples/rs_change_status.php:
--------------------------------------------------------------------------------
1 | changeStatus($bucket, $key, $status);
25 | if ($err != null) {
26 | var_dump($err);
27 | } else {
28 | var_dump($ret);
29 | }
30 |
--------------------------------------------------------------------------------
/examples/delete_bucketEvent.php:
--------------------------------------------------------------------------------
1 | deleteBucketEvent($bucket, $name);
24 | if ($err != null) {
25 | var_dump($err);
26 | } else {
27 | var_dump($ret);
28 | }
29 |
--------------------------------------------------------------------------------
/examples/rs_batch_delete.php:
--------------------------------------------------------------------------------
1 | buildBatchDelete($bucket, $keys);
27 | list($ret, $err) = $bucketManager->batch($ops);
28 | if ($err != null) {
29 | var_dump($err);
30 | } else {
31 | var_dump($ret);
32 | }
33 |
--------------------------------------------------------------------------------
/examples/rs_batch_stat.php:
--------------------------------------------------------------------------------
1 | buildBatchStat($bucket, $keys);
27 | list($ret, $err) = $bucketManager->batch($ops);
28 | if ($err != null) {
29 | var_dump($err);
30 | } else {
31 | var_dump($ret);
32 | }
33 |
--------------------------------------------------------------------------------
/examples/cdn_get_log_list.php:
--------------------------------------------------------------------------------
1 | getCdnLogList($domains, $logDate);
26 | if ($getLogErr != null) {
27 | var_dump($getLogErr);
28 | } else {
29 | echo "get cdn log list success\n";
30 | print_r($logListData);
31 | }
32 |
--------------------------------------------------------------------------------
/examples/sms/sms_query_template.php:
--------------------------------------------------------------------------------
1 | queryTemplate($audit_status, $page, $page_size);
23 | echo "\n====> query template result: \n";
24 | if ($err !== null) {
25 | var_dump($err);
26 | } else {
27 | var_dump($ret);
28 | }
29 |
--------------------------------------------------------------------------------
/examples/sms/sms_query_signature.php:
--------------------------------------------------------------------------------
1 | querySignature($audit_status, $page, $page_size);
23 | echo "\n====> query signature result: \n";
24 | if ($err !== null) {
25 | var_dump($err);
26 | } else {
27 | var_dump($ret);
28 | }
29 |
--------------------------------------------------------------------------------
/src/Qiniu/Http/Middleware/Middleware.php:
--------------------------------------------------------------------------------
1 | $middlewares
19 | * @param callable(Request): Response $handler
20 | * @return callable(Request): Response
21 | */
22 | function compose($middlewares, $handler)
23 | {
24 | $next = $handler;
25 | foreach (array_reverse($middlewares) as $middleware) {
26 | $next = function ($request) use ($middleware, $next) {
27 | return $middleware->send($request, $next);
28 | };
29 | }
30 | return $next;
31 | }
32 |
--------------------------------------------------------------------------------
/examples/rs_move.php:
--------------------------------------------------------------------------------
1 | move($srcBucket, $srcKey, $destBucket, $destKey, true);
25 | if ($err != null) {
26 | var_dump($err);
27 | } else {
28 | var_dump($ret);
29 | }
30 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/DownloadTest.php:
--------------------------------------------------------------------------------
1 | privateDownloadUrl($base_url);
15 | $response = Client::get($private_url);
16 | $this->assertEquals(200, $response->statusCode);
17 | }
18 |
19 | public function testFop()
20 | {
21 | global $testAuth;
22 | $base_url = 'http://sdk.peterpy.cn/gogopher.jpg?exif';
23 | $private_url = $testAuth->privateDownloadUrl($base_url);
24 | $response = Client::get($private_url);
25 | $this->assertEquals(200, $response->statusCode);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/examples/sms/sms_send_message.php:
--------------------------------------------------------------------------------
1 | 'xxxx');
25 |
26 | list($ret, $err) = $client->sendMessage($template_id, $mobiles, $code);
27 | if ($err !== null) {
28 | var_dump($err);
29 | } else {
30 | echo "\n====> Send Message Successfully: \n";
31 | var_dump($ret);
32 | }
33 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_createApp.php:
--------------------------------------------------------------------------------
1 | createApp($hub, $title, $maxUsers);
27 | if ($err !== null) {
28 | var_dump($err);
29 | } else {
30 | echo "\n====> Create Successfully: \n";
31 | var_dump($ret);
32 | }
33 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_rooms_listActiveRooms.php:
--------------------------------------------------------------------------------
1 | listActiveRooms($appId, $prefix, $offset, $limit);
30 | if ($err !== null) {
31 | var_dump($err);
32 | } else {
33 | echo "\n====> Active Rooms:\n";
34 | var_dump($ret);
35 | }
36 |
--------------------------------------------------------------------------------
/examples/rsf_v2list_bucket.php:
--------------------------------------------------------------------------------
1 | listFilesv2($bucket, $prefix, $marker, $limit, $delimiter, true);
30 | if ($err != null) {
31 | var_dump($err);
32 | } else {
33 | var_dump($ret);
34 | }
35 |
--------------------------------------------------------------------------------
/examples/rs_copy.php:
--------------------------------------------------------------------------------
1 | copy($srcBucket, $srcKey, $destBucket, $destKey, true);
29 | if ($err != null) {
30 | var_dump($err);
31 | } else {
32 | var_dump($ret);
33 | }
34 |
--------------------------------------------------------------------------------
/examples/rs_change_type.php:
--------------------------------------------------------------------------------
1 | changeType($bucket, $key, $fileType);
32 | if ($err != null) {
33 | var_dump($err);
34 | } else {
35 | var_dump($ret);
36 | }
37 |
--------------------------------------------------------------------------------
/examples/sms/sms_create_signature.php:
--------------------------------------------------------------------------------
1 | createSignature($signature, $source, $pics);
23 |
24 | echo "\n====> create signature result: \n";
25 | if ($err !== null) {
26 | var_dump($err);
27 | } else {
28 | var_dump($ret);
29 | }
30 |
--------------------------------------------------------------------------------
/examples/rs_batch_change_mime.php:
--------------------------------------------------------------------------------
1 | 'video/x-mp4',
22 | 'qiniu.png' => 'image/x-png',
23 | 'qiniu.jpg' => 'image/x-jpg'
24 | );
25 |
26 | $ops = $bucketManager->buildBatchChangeMime($bucket, $keyMimePairs);
27 | list($ret, $err) = $bucketManager->batch($ops);
28 | if ($err != null) {
29 | var_dump($err);
30 | } else {
31 | var_dump($ret);
32 | }
33 |
--------------------------------------------------------------------------------
/src/Qiniu/Http/Request.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | public $headers;
15 |
16 | /**
17 | * @var mixed|null
18 | */
19 | public $body;
20 |
21 | /**
22 | * @var string
23 | */
24 | public $method;
25 |
26 | /**
27 | * @var RequestOptions
28 | */
29 | public $opt;
30 |
31 | public function __construct($method, $url, array $headers = array(), $body = null, $opt = null)
32 | {
33 | $this->method = strtoupper($method);
34 | $this->url = $url;
35 | $this->headers = $headers;
36 | $this->body = $body;
37 | if ($opt === null) {
38 | $opt = new RequestOptions();
39 | }
40 | $this->opt = $opt;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # 贡献代码指南
2 |
3 | 我们非常欢迎大家来贡献代码,我们会向贡献者致以最诚挚的敬意。
4 |
5 | 一般可以通过在Github上提交[Pull Request](https://github.com/qiniu/php-sdk)来贡献代码。
6 |
7 | ## Pull Request要求
8 |
9 | - **[PSR-2 编码风格标准](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** 。要通过项目中的code sniffer检查。
10 |
11 | - **代码格式** 提交前 请按 ./vendor/bin/phpcbf --standard=PSR2 进行格式化。
12 |
13 | - **必须添加测试!** - 如果没有测试(单元测试、集成测试都可以),那么提交的补丁是不会通过的。
14 |
15 | - **记得更新文档** - 保证`README.md`以及其他相关文档及时更新,和代码的变更保持一致性。
16 |
17 | - **考虑我们的发布周期** - 我们的版本号会服从[SemVer v2.0.0](http://semver.org/),我们绝对不会随意变更对外的API。
18 |
19 | - **创建feature分支** - 最好不要从你的master分支提交 pull request。
20 |
21 | - **一个feature提交一个pull请求** - 如果你的代码变更了多个操作,那就提交多个pull请求吧。
22 |
23 | - **清晰的commit历史** - 保证你的pull请求的每次commit操作都是有意义的。如果你开发中需要执行多次的即时commit操作,那么请把它们放到一起再提交pull请求。
24 |
25 | ## 运行测试
26 |
27 | ``` bash
28 | ./vendor/bin/phpunit tests/Qiniu/Tests/
29 |
30 | ```
31 |
--------------------------------------------------------------------------------
/examples/update_bucketEvent.php:
--------------------------------------------------------------------------------
1 | updateBucketEvent($bucket, $name, $prefix, $suffix, $event, $callbackURL);
27 | if ($err != null) {
28 | var_dump($err);
29 | } else {
30 | var_dump($ret);
31 | }
32 |
--------------------------------------------------------------------------------
/examples/cdn_get_flux.php:
--------------------------------------------------------------------------------
1 | getFluxData($domains, $startDate, $endDate, $granularity);
30 | if ($getFluxErr != null) {
31 | var_dump($getFluxErr);
32 | } else {
33 | echo "get flux data success\n";
34 | print_r($fluxData);
35 | }
36 |
--------------------------------------------------------------------------------
/examples/sms/sms_edit_signature.php:
--------------------------------------------------------------------------------
1 | updateSignature($id, $signature, $source, $pics);
24 |
25 | echo "\n====> edit signature result: \n";
26 | if ($err !== null) {
27 | var_dump($err);
28 | } else {
29 | echo "\n====> Update Signature Successfully\n";
30 | }
31 |
--------------------------------------------------------------------------------
/examples/update_bucketLifecycleRule.php:
--------------------------------------------------------------------------------
1 | updateBucketLifecycleRule(
26 | $bucket,
27 | $name,
28 | $prefix,
29 | $delete_after_days,
30 | $to_line_after_days
31 | );
32 | if ($err != null) {
33 | var_dump($err);
34 | } else {
35 | var_dump($ret);
36 | }
37 |
--------------------------------------------------------------------------------
/examples/upload_simple_file.php:
--------------------------------------------------------------------------------
1 | uploadToken($bucket);
20 |
21 | // 要上传文件的本地路径
22 | $filePath = './php-logo.png';
23 |
24 | // 上传到七牛存储后保存的文件名
25 | $key = 'my-php-logo.png';
26 |
27 | // 初始化 UploadManager 对象并进行文件的上传。
28 | $uploadMgr = new UploadManager();
29 |
30 | // 调用 UploadManager 的 putFile 方法进行文件的上传,该方法会判断文件大小,进而决定使用表单上传还是分片上传,无需手动配置。
31 | list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath);
32 | echo "\n====> putFile result: \n";
33 | if ($err !== null) {
34 | var_dump($err);
35 | } else {
36 | var_dump($ret);
37 | }
38 |
--------------------------------------------------------------------------------
/examples/put_bucketEvent.php:
--------------------------------------------------------------------------------
1 | putBucketEvent($bucket, $name, $prefix, $suffix, $event, $callbackURL);
28 | if ($err != null) {
29 | var_dump($err);
30 | } else {
31 | var_dump($ret);
32 | }
33 |
--------------------------------------------------------------------------------
/examples/rs_batch_delete_after_days.php:
--------------------------------------------------------------------------------
1 | buildBatchDeleteAfterDays($bucket, $keyDayPairs);
34 | list($ret, $err) = $bucketManager->batch($ops);
35 | if ($err != null) {
36 | var_dump($err);
37 | } else {
38 | var_dump($ret);
39 | }
40 |
--------------------------------------------------------------------------------
/src/Qiniu/Http/Proxy.php:
--------------------------------------------------------------------------------
1 | proxy = $proxy;
16 | $this->proxy_auth = $proxy_auth;
17 | $this->proxy_user_password = $proxy_user_password;
18 | }
19 |
20 | public function makeReqOpt()
21 | {
22 | $reqOpt = new RequestOptions();
23 | if ($this->proxy !== null) {
24 | $reqOpt->proxy = $this->proxy;
25 | }
26 | if ($this->proxy_auth !== null) {
27 | $reqOpt->proxy_auth = $this->proxy_auth;
28 | }
29 | if ($this->proxy_user_password !== null) {
30 | $reqOpt->proxy_user_password = $this->proxy_user_password;
31 | }
32 | return $reqOpt;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/examples/put_referAntiLeech.php:
--------------------------------------------------------------------------------
1 | putReferAntiLeech($bucket, $mode, $norefer, $pattern);
26 | if ($err != null) {
27 | var_dump($err);
28 | } else {
29 | var_dump($ret);
30 | }
31 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_create_roomToken.php:
--------------------------------------------------------------------------------
1 | appToken($appId, $roomName, $userId, $expireAt, $permission);
33 | echo "\n====> Create RoomToken Successfully: \n";
34 | var_dump($RoomToken);
35 |
--------------------------------------------------------------------------------
/examples/rs_batch_copy.php:
--------------------------------------------------------------------------------
1 | buildBatchCopy($srcBucket, $keyPairs, $destBucket, true);
35 | list($ret, $err) = $bucketManager->batch($ops);
36 | if ($err != null) {
37 | var_dump($err);
38 | } else {
39 | var_dump($ret);
40 | }
41 |
--------------------------------------------------------------------------------
/examples/upload_and_callback.php:
--------------------------------------------------------------------------------
1 | 'http://your.domain.com/upload_verify_callback.php',
17 | 'callbackBody' => 'filename=$(fname)&filesize=$(fsize)'
18 | );
19 | $uptoken = $auth->uploadToken($bucket, null, 3600, $policy);
20 |
21 | // 上传文件的本地路径
22 | $filePath = './php-logo.png';
23 |
24 | $uploadMgr = new UploadManager();
25 | list($ret, $err) = $uploadMgr->putFile($uptoken, null, $filePath);
26 | echo "\n====> putFile result: \n";
27 | if ($err !== null) {
28 | var_dump($err);
29 | } else {
30 | var_dump($ret);
31 | }
32 |
--------------------------------------------------------------------------------
/examples/cdn_get_bandwidth.php:
--------------------------------------------------------------------------------
1 | getBandwidthData(
30 | $domains,
31 | $startDate,
32 | $endDate,
33 | $granularity
34 | );
35 |
36 | if ($getBandwidthErr != null) {
37 | var_dump($getBandwidthErr);
38 | } else {
39 | echo "get bandwidth data success\n";
40 | print_r($bandwidthData);
41 | }
42 |
--------------------------------------------------------------------------------
/examples/rs_batch_restore_ar.php:
--------------------------------------------------------------------------------
1 | batch($ops);
37 | if ($err != null) {
38 | var_dump($err);
39 | } else {
40 | var_dump($ret);
41 | }
42 |
--------------------------------------------------------------------------------
/examples/rs_batch_move.php:
--------------------------------------------------------------------------------
1 | buildBatchMove($srcBucket, $keyPairs, $destBucket, true);
35 | list($ret, $err) = $bucketManager->batch($ops);
36 | if ($err != null) {
37 | var_dump($err);
38 | } else {
39 | var_dump($ret);
40 | }
41 |
--------------------------------------------------------------------------------
/examples/rsf_list_files.php:
--------------------------------------------------------------------------------
1 | listFiles($bucket, $prefix, $marker, $limit, $delimiter);
31 | if ($err !== null) {
32 | echo "\n====> list file err: \n";
33 | var_dump($err);
34 | } else {
35 | if (array_key_exists('marker', $ret)) {
36 | echo "Marker:" . $ret["marker"] . "\n";
37 | }
38 | echo "\nList Iterms====>\n";
39 | }
40 |
--------------------------------------------------------------------------------
/examples/sms/sms_edit_template.php:
--------------------------------------------------------------------------------
1 | updateTemplate($template_id, $name, $template, $description, $signature_id);
25 |
26 | echo "\n====> edit template result: \n";
27 | if ($err !== null) {
28 | var_dump($err);
29 | } else {
30 | echo "\n====> Update Template Successfully\n";
31 | }
32 |
--------------------------------------------------------------------------------
/examples/saveas.php:
--------------------------------------------------------------------------------
1 | 为生成缩略图的文件名
15 | $entry = ':';
16 |
17 | // 生成的值
18 | $encodedEntryURI = \Qiniu\base64_urlSafeEncode($entry);
19 |
20 | // 使用 SecretKey 对新的下载 URL 进行 HMAC1-SHA1 签名
21 | $newurl = "78re52.com1.z0.glb.clouddn.com/resource/Ship.jpg?imageView2/2/w/200/h/200|saveas/" . $encodedEntryURI;
22 |
23 | $sign = hash_hmac("sha1", $newurl, $secretKey, true);
24 |
25 | // 对签名进行 URL 安全的 Base64 编码
26 | $encodedSign = \Qiniu\base64_urlSafeEncode($sign);
27 |
28 | // 最终得到的完整下载 URL
29 | $finalURL = "http://" . $newurl . "/sign/" . $accessKey . ":" . $encodedSign;
30 |
31 | $callbackBody = file_get_contents("$finalURL");
32 |
33 | echo $callbackBody;
34 |
--------------------------------------------------------------------------------
/examples/censor_image.php:
--------------------------------------------------------------------------------
1 | censorImage($body);
37 | echo "\n====> Result is: \n";
38 | if ($err !== null) {
39 | var_dump($err);
40 | } else {
41 | var_dump($ret);
42 | }
43 |
--------------------------------------------------------------------------------
/examples/upload_verify_callback.php:
--------------------------------------------------------------------------------
1 | verifyCallback($contentType, $authorization, $url, $callbackBody);
27 |
28 | if ($isQiniuCallback) {
29 | $resp = array('ret' => 'success');
30 | } else {
31 | $resp = array('ret' => 'failed');
32 | }
33 |
34 | echo json_encode($resp);
35 |
--------------------------------------------------------------------------------
/examples/upload_with_zone.php:
--------------------------------------------------------------------------------
1 | uploadToken($bucket);
20 |
21 | // 上传文件的本地路径
22 | $filePath = './php-logo.png';
23 |
24 | // 指定 zone 上传
25 | // 参考文档:https://developer.qiniu.com/kodo/manual/1671/region-endpoint
26 | $zone = Zone::zonez0(); // 华东:z0,华北:z1,华南:z2,北美:na0,东南亚:as0
27 | $config = new Config($zone);
28 | $config->useHTTPS = true;
29 |
30 | // 指定 config
31 | $uploadMgr = new UploadManager($config);
32 |
33 | list($ret, $err) = $uploadMgr->putFile($uptoken, $key, $filePath);
34 | echo "\n====> putFile result: \n";
35 | if ($err !== null) {
36 | var_dump($err);
37 | } else {
38 | var_dump($ret);
39 | }
40 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | ci:
3 | - prow.qiniu.io # prow 里面运行需添加,其他 CI 不要
4 | require_ci_to_pass: no # 改为 no,否则 codecov 会等待其他 GitHub 上所有 CI 通过才会留言。
5 |
6 | github_checks: #关闭github checks
7 | annotations: false
8 |
9 | comment:
10 | layout: "reach, diff, flags, files"
11 | behavior: new # 默认是更新旧留言,改为 new,删除旧的,增加新的。
12 | require_changes: false # if true: only post the comment if coverage changes
13 | require_base: no # [yes :: must have a base report to post]
14 | require_head: yes # [yes :: must have a head report to post]
15 | branches: # branch names that can post comment
16 | - "master"
17 |
18 | coverage:
19 | status: # 评判 pr 通过的标准
20 | patch: off
21 | project: # project 统计所有代码x
22 | default:
23 | # basic
24 | target: 85% # 总体通过标准
25 | threshold: 3% # 允许单次下降的幅度
26 | base: auto
27 | if_not_found: success
28 | if_ci_failed: error
29 |
--------------------------------------------------------------------------------
/examples/rs_batch_change_type.php:
--------------------------------------------------------------------------------
1 | batch($ops);
41 | if ($err != null) {
42 | var_dump($err);
43 | } else {
44 | var_dump($ret);
45 | }
46 |
--------------------------------------------------------------------------------
/examples/sms/sms_create_template.php:
--------------------------------------------------------------------------------
1 | createTemplate($name, $template, $type, $description, $signature_id);
27 |
28 | echo "\n====> create signature result: \n";
29 | if ($err !== null) {
30 | var_dump($err);
31 | } else {
32 | var_dump($ret);
33 | }
34 |
--------------------------------------------------------------------------------
/examples/upload_with_qvmzone.php:
--------------------------------------------------------------------------------
1 | uploadToken($bucket);
20 |
21 | // 上传文件的本地路径
22 | $filePath = './php-logo.png';
23 |
24 | // 七牛云主机QVM和七牛对象存储KODO内网上传,目前支持华东1区域(杭州)和华北2区域(北京)的云主机可以访问同区域的对象存储服务
25 | // 参考文档:https://developer.qiniu.com/qvm/manual/4269/qvm-kodo
26 |
27 | $zone = Zone::qvmZonez0(); // 华东:z0,华北:z1
28 | $config = new Config($zone);
29 | $config->useHTTPS = true;
30 |
31 | // 指定 config
32 | $uploadMgr = new UploadManager($config);
33 |
34 | list($ret, $err) = $uploadMgr->putFile($uptoken, $key, $filePath);
35 | echo "\n====> putFile result: \n";
36 | if ($err !== null) {
37 | var_dump($err);
38 | } else {
39 | var_dump($ret);
40 | }
41 |
--------------------------------------------------------------------------------
/examples/rtc/rtc_updateApp.php:
--------------------------------------------------------------------------------
1 | updateApp($appId, $hub, $title, $maxUsers, false, $mergePublishRtmp);
35 | if ($err !== null) {
36 | var_dump($err);
37 | } else {
38 | echo "\n====> Update $appId Conf Successfully: \n";
39 | var_dump($ret);
40 | }
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Qiniu, Ltd.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "qiniu/php-sdk",
3 | "type": "library",
4 | "description": "Qiniu Resource (Cloud) Storage SDK for PHP",
5 | "keywords": [
6 | "qiniu",
7 | "storage",
8 | "sdk",
9 | "cloud"
10 | ],
11 | "homepage": "http://developer.qiniu.com/",
12 | "license": "MIT",
13 | "authors": [
14 | {
15 | "name": "Qiniu",
16 | "email": "sdk@qiniu.com",
17 | "homepage": "http://www.qiniu.com"
18 | }
19 | ],
20 | "require": {
21 | "php": ">=5.3.3",
22 | "ext-xml": "*",
23 | "ext-curl": "*",
24 | "myclabs/php-enum": "~1.5.2 || ~1.6.6 || ~1.7.7 || ~1.8.4"
25 | },
26 | "require-dev": {
27 | "paragonie/random_compat": ">=2",
28 | "phpunit/phpunit": "^4.8 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4",
29 | "squizlabs/php_codesniffer": "^2.3 || ~3.6"
30 | },
31 | "autoload": {
32 | "psr-4": {
33 | "Qiniu\\": "src/Qiniu"
34 | },
35 | "files": [
36 | "src/Qiniu/functions.php",
37 | "src/Qiniu/Http/Middleware/Middleware.php"
38 | ]
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | filter:
2 | excluded_paths: [tests/*]
3 | checks:
4 | php:
5 | code_rating: true
6 | remove_extra_empty_lines: true
7 | remove_php_closing_tag: true
8 | remove_trailing_whitespace: true
9 | fix_use_statements:
10 | remove_unused: true
11 | preserve_multiple: false
12 | preserve_blanklines: true
13 | order_alphabetically: true
14 | fix_php_opening_tag: true
15 | fix_linefeed: true
16 | fix_line_ending: true
17 | fix_identation_4spaces: true
18 | fix_doc_comments: true
19 | tools:
20 | external_code_coverage:
21 | timeout: 1200
22 | runs: 3
23 | php_analyzer: true
24 | php_code_coverage: false
25 | php_code_sniffer:
26 | config:
27 | standard: PSR2
28 | filter:
29 | paths: ['src']
30 | php_loc:
31 | enabled: true
32 | excluded_dirs: [vendor, tests]
33 | php_cpd:
34 | enabled: true
35 | excluded_dirs: [vendor, tests]
36 | build:
37 | nodes:
38 | analysis:
39 | tests:
40 | override:
41 | - php-scrutinizer-run
42 |
43 |
--------------------------------------------------------------------------------
/examples/censor_video.php:
--------------------------------------------------------------------------------
1 | censorVideo($body);
37 | echo "\n====> Result is: \n";
38 | if ($err !== null) {
39 | var_dump($err);
40 | } else {
41 | echo "job_id is: $jobid\n";
42 | }
43 |
44 | // 查询视频审核结果
45 | list($ret, $err) = $argusManager->censorStatus($jobid);
46 | echo "\n====> job status: \n";
47 |
48 | if ($err != null) {
49 | var_dump($err);
50 | } else {
51 | var_dump($ret);
52 | }
53 |
--------------------------------------------------------------------------------
/examples/cdn_get_prefetch_list.php:
--------------------------------------------------------------------------------
1 | getCdnPrefetchList(
33 | $requestId,
34 | $urls,
35 | $state,
36 | $pageNo,
37 | $pageSize,
38 | $startTime,
39 | $endTime
40 | );
41 | echo "\n====> query prefetch list: \n";
42 | if ($err !== null) {
43 | var_dump($err);
44 | } else {
45 | var_dump($ret);
46 | }
47 |
--------------------------------------------------------------------------------
/examples/sms/sms_query_send_sms.php:
--------------------------------------------------------------------------------
1 | querySendSms(
34 | $job_id,
35 | $message_id,
36 | $mobile,
37 | $status,
38 | $template_id,
39 | $type,
40 | $start,
41 | $end,
42 | $page,
43 | $page_size
44 | );
45 | echo "\n====> query send sms result: \n";
46 | if ($err !== null) {
47 | var_dump($err);
48 | } else {
49 | var_dump($ret);
50 | }
51 |
--------------------------------------------------------------------------------
/examples/rs_fetch.php:
--------------------------------------------------------------------------------
1 | fetch($url, $bucket, $key);
26 | echo "=====> fetch $url to bucket: $bucket key: $key\n";
27 | if ($err !== null) {
28 | var_dump($err);
29 | } else {
30 | print_r($ret);
31 | }
32 |
33 | //---------------------------------------- demo2 ----------------------------------------
34 | // 不指定 key 时,以文件内容的 hash 作为文件名
35 |
36 | $key = null;
37 | list($ret, $err) = $bucketManager->fetch($url, $bucket, $key);
38 | echo "=====> fetch $url to bucket: $bucket key: $(etag)\n";
39 | if ($err !== null) {
40 | var_dump($err);
41 | } else {
42 | print_r($ret);
43 | }
44 |
--------------------------------------------------------------------------------
/examples/bucket_lifecycleRule.php:
--------------------------------------------------------------------------------
1 | bucketLifecycleRule(
29 | $bucket,
30 | $name,
31 | $prefix,
32 | $delete_after_days,
33 | $to_line_after_days,
34 | $to_archive_after_days,
35 | $to_deep_archive_after_days,
36 | $to_archive_ir_after_days
37 | );
38 | if ($err != null) {
39 | var_dump($err);
40 | } else {
41 | var_dump($ret);
42 | }
43 |
--------------------------------------------------------------------------------
/src/Qiniu/Zone.php:
--------------------------------------------------------------------------------
1 | execute('gogopher.jpg', 'exif');
15 | $this->assertNull($error);
16 | $this->assertNotNull($exif);
17 | }
18 |
19 | public function testExifPrivate()
20 | {
21 | global $testAuth;
22 | $fop = new Operation('private-res.qiniudn.com', $testAuth);
23 | list($exif, $error) = $fop->execute('noexif.jpg', 'exif');
24 | $this->assertNotNull($error);
25 | $this->assertNull($exif);
26 | }
27 |
28 | public function testbuildUrl()
29 | {
30 | $fops = 'imageView2/2/h/200';
31 | $fop = new Operation('testres.qiniudn.com');
32 | $url = $fop->buildUrl('gogopher.jpg', $fops);
33 | $this->assertEquals($url, 'http://testres.qiniudn.com/gogopher.jpg?imageView2/2/h/200');
34 |
35 | $fops = array('imageView2/2/h/200', 'imageInfo');
36 | $url = $fop->buildUrl('gogopher.jpg', $fops);
37 | $this->assertEquals($url, 'http://testres.qiniudn.com/gogopher.jpg?imageView2/2/h/200|imageInfo');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/examples/rsf_list_bucket.php:
--------------------------------------------------------------------------------
1 | listFiles($bucket, $prefix, $marker, $limit, $delimiter);
31 | if ($err !== null) {
32 | echo "\n====> list file err: \n";
33 | var_dump($err);
34 | } else {
35 | $marker = null;
36 | if (array_key_exists('marker', $ret)) {
37 | $marker = $ret['marker'];
38 | }
39 | echo "Marker: $marker\n";
40 | echo "\nList Items====>\n";
41 | //var_dump($ret['items']);
42 | print('items count:' . count($ret['items']) . "\n");
43 | if (array_key_exists('commonPrefixes', $ret)) {
44 | print_r($ret['commonPrefixes']);
45 | }
46 | }
47 | } while (!empty($marker));
48 |
--------------------------------------------------------------------------------
/examples/cdn_get_refresh_list.php:
--------------------------------------------------------------------------------
1 | getCdnRefreshList(
34 | $requestId,
35 | $isDir,
36 | $urls,
37 | $state,
38 | $pageNo,
39 | $pageSize,
40 | $startTime,
41 | $endTime
42 | );
43 | echo "\n====> query refresh list: \n";
44 | if ($err !== null) {
45 | var_dump($err);
46 | } else {
47 | var_dump($ret);
48 | }
49 |
--------------------------------------------------------------------------------
/examples/upload_and_pfop.php:
--------------------------------------------------------------------------------
1 | $pfop,
38 | 'persistentNotifyUrl' => $notifyUrl,
39 | 'persistentPipeline' => $pipeline
40 | );
41 | $token = $auth->uploadToken($bucket, null, 3600, $policy);
42 |
43 | list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath);
44 | echo "\n====> putFile result: \n";
45 | if ($err !== null) {
46 | var_dump($err);
47 | } else {
48 | var_dump($ret);
49 | }
50 |
--------------------------------------------------------------------------------
/examples/rtc/README.md:
--------------------------------------------------------------------------------
1 | # Rtc Streaming Cloud Server-Side Library For PHP
2 |
3 | ## Features
4 |
5 | - RoomToken 签发
6 | - [x] 生成 RoomToken: client->appToken()
7 |
8 | - App 管理
9 | - [x] 创建应用: client->createApp()
10 | - [x] 获取应用配置信息: client->getApp()
11 | - [x] 更新应用配置信息: client->updateApp()
12 | - [x] 删除应用: client->deleteApp()
13 |
14 | - 房间管理
15 | - [x] 列举房间下的所有用户: client->listUser()
16 | - [x] 指定一个用户踢出房间: client->kickUser()
17 | - [x] 停止一个房间的合流转推: client->stopMerge()
18 | - [x] 获取当前所有活跃的房间: client->listActiveRooms()
19 |
20 | ## Demo
21 | - RoomToken 签发
22 | - [生成 RoomToken](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_create_roomToken.php)
23 |
24 | - App 管理
25 | - [创建应用](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_createApp.php)
26 | - [获取应用配置信息](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_getApp.php)
27 | - [更新应用配置信息](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_updateApp.php)
28 | - [删除应用](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_deleteApp.php)
29 |
30 | - 房间管理
31 | - [列举房间下的所有用户](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_rooms_listUser.php)
32 | - [指定一个用户踢出房间](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_rooms_kickUser.php)
33 | - [停止一个房间的合流转推](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_rooms_stopMerge.php)
34 | - [获取当前所有活跃的房间](https://github.com/qiniu/php-sdk/tree/master/examples/rtc/rtc_rooms_listActiveRooms.php)
--------------------------------------------------------------------------------
/src/Qiniu/Enum/QiniuEnum.php:
--------------------------------------------------------------------------------
1 | useHTTPS=true;
31 |
32 | // 视频处理完毕后保存到空间中的名称
33 | $saveasKey = 'qiniu_640x360.mp4';
34 |
35 | $pfop = new PersistentFop($auth, $config);
36 |
37 | // 进行视频转码操作
38 | $fops = "avthumb/mp4/s/640x360/vb/1.4m|saveas/" . \Qiniu\base64_urlSafeEncode("$bucket:$saveasKey");
39 |
40 | list($id, $err) = $pfop->execute($bucket, $key, $fops, $pipeline, $notifyUrl, $force);
41 | echo "\n====> pfop avthumb result: \n";
42 | if ($err != null) {
43 | var_dump($err);
44 | } else {
45 | echo "PersistentFop Id: $id\n";
46 | }
47 |
48 | // 查询转码的进度和状态
49 | list($ret, $err) = $pfop->status($id);
50 | echo "\n====> pfop avthumb status: \n";
51 | if ($err != null) {
52 | var_dump($err);
53 | } else {
54 | var_dump($ret);
55 | }
56 |
--------------------------------------------------------------------------------
/examples/pfop_vframe.php:
--------------------------------------------------------------------------------
1 | useHTTPS = true;
31 | $pfop = new PersistentFop($auth, $config);
32 |
33 | // 视频处理完毕后保存到空间中的名称
34 | $saveasKey = 'qiniu_480x360.jpg';
35 |
36 | // 进行视频截帧操作
37 | $fops = "vframe/jpg/offset/1/w/480/h/360/rotate/90|saveas/" .
38 | \Qiniu\base64_urlSafeEncode("$bucket:$saveasKey");
39 |
40 | list($id, $err) = $pfop->execute($bucket, $key, $fops, $pipeline, $notifyUrl, $force);
41 | echo "\n====> pfop avthumb result: \n";
42 | if ($err != null) {
43 | var_dump($err);
44 | } else {
45 | echo "PersistentFop Id: $id\n";
46 | }
47 |
48 | // 查询转码的进度和状态
49 | list($ret, $err) = $pfop->status($id);
50 | echo "\n====> pfop avthumb status: \n";
51 | if ($err != null) {
52 | var_dump($err);
53 | } else {
54 | var_dump($ret);
55 | }
56 |
--------------------------------------------------------------------------------
/examples/pfop_mkzip.php:
--------------------------------------------------------------------------------
1 | execute($bucket, $key, $fops, $pipeline, $notify_url, $force);
43 |
44 | echo "\n====> pfop mkzip result: \n";
45 | if ($err != null) {
46 | var_dump($err);
47 | } else {
48 | echo "PersistentFop Id: $id\n";
49 | }
50 |
51 | // 查询转码的进度和状态
52 | list($ret, $err) = $pfop->status($id);
53 | echo "\n====> pfop mkzip status: \n";
54 | if ($err != null) {
55 | var_dump($err);
56 | } else {
57 | var_dump($ret);
58 | }
59 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/EtagTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('Fto5o-5ea0sNMlW_75VgGJCv2AcJ', $r);
16 | $this->assertNull($error);
17 | }
18 |
19 | public function testLess4M()
20 | {
21 | $file = qiniuTempFile(3 * 1024 * 1024, false);
22 | list($r, $error) = Etag::sum($file);
23 | unlink($file);
24 | $this->assertEquals('Fs5BpnAjRykYTg6o5E09cjuXrDkG', $r);
25 | $this->assertNull($error);
26 | }
27 |
28 | public function test4M()
29 | {
30 | $file = qiniuTempFile(4 * 1024 * 1024, false);
31 | list($r, $error) = Etag::sum($file);
32 | unlink($file);
33 | $this->assertEquals('FiuKULnybewpEnrfTmxjsxc-3dWp', $r);
34 | $this->assertNull($error);
35 | }
36 |
37 | public function testMore4M()
38 | {
39 | $file = qiniuTempFile(5 * 1024 * 1024, false);
40 | list($r, $error) = Etag::sum($file);
41 | unlink($file);
42 | $this->assertEquals('lhvyfIWMYFTq4s4alzlhXoAkqfVL', $r);
43 | $this->assertNull($error);
44 | }
45 |
46 | public function test8M()
47 | {
48 | $file = qiniuTempFile(8 * 1024 * 1024, false);
49 | list($r, $error) = Etag::sum($file);
50 | unlink($file);
51 | $this->assertEquals('lmRm9ZfGZ86bnMys4wRTWtJj9ClG', $r);
52 | $this->assertNull($error);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/examples/pfop_watermark.php:
--------------------------------------------------------------------------------
1 | useHTTPS=true;
32 | $pfop = new PersistentFop($auth, $config);
33 |
34 | // 图片水印的源路径,也就是给视频打图片水印的图片
35 | $base64URL = Qiniu\base64_urlSafeEncode('http://test-2.qiniudn.com/logo.png');
36 |
37 | // 视频处理完毕后保存到空间中的名称
38 | $saveasKey = 'qiniu_watermark.mp4';
39 |
40 | // 进行视频打图片水印操作
41 | $fops = "avthumb/mp4/wmImage/" . $base64URL . "|saveas/"
42 | . \Qiniu\base64_urlSafeEncode("$bucket:$saveasKey");
43 |
44 | list($id, $err) = $pfop->execute($bucket, $key, $fops, $pipeline, $notifyUrl, $force);
45 | echo "\n====> pfop avthumb result: \n";
46 | if ($err != null) {
47 | var_dump($err);
48 | } else {
49 | echo "PersistentFop Id: $id\n";
50 | }
51 |
52 | // 查询转码的进度和状态
53 | list($ret, $err) = $pfop->status($id);
54 | echo "\n====> pfop avthumb status: \n";
55 | if ($err != null) {
56 | var_dump($err);
57 | } else {
58 | var_dump($ret);
59 | }
60 |
--------------------------------------------------------------------------------
/examples/cdn_refresh_urls_dirs.php:
--------------------------------------------------------------------------------
1 | refreshUrlsAndDirs($urls, $dirs);
32 | if ($refreshErr != null) {
33 | var_dump($refreshErr);
34 | } else {
35 | echo "refresh request sent\n";
36 | print_r($refreshResult);
37 | }
38 |
39 | //---------------------------------------- demo2 ----------------------------------------
40 | // 刷新文件
41 |
42 | list($refreshResult, $refreshErr) = $cdnManager->refreshUrls($urls);
43 | if ($refreshErr != null) {
44 | var_dump($refreshErr);
45 | } else {
46 | echo "refresh urls request sent\n";
47 | print_r($refreshResult);
48 | }
49 |
50 | //---------------------------------------- demo3 ----------------------------------------
51 | // 刷新目录
52 |
53 | list($refreshResult, $refreshErr) = $cdnManager->refreshDirs($dirs);
54 | if ($refreshErr != null) {
55 | var_dump($refreshErr);
56 | } else {
57 | echo "refresh dirs request sent\n";
58 | print_r($refreshResult);
59 | }
60 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | 0) {
49 | $length = min($rest_size, 4 * 1024);
50 | if (fwrite($file, random_bytes($length)) == false) {
51 | return false;
52 | }
53 | $rest_size -= $length;
54 | }
55 | } else if ($size > 0) {
56 | fseek($file, $size - 1);
57 | fwrite($file, ' ');
58 | }
59 | fclose($file);
60 | return $fileName;
61 | }
62 |
--------------------------------------------------------------------------------
/examples/sms/README.md:
--------------------------------------------------------------------------------
1 | # SMS Server-Side Library For PHP
2 |
3 | ## Features
4 |
5 | - 签名管理
6 | - [x] 创建签名: client->createSignature()
7 | - [x] 列出签名: client->checkSignature()
8 | - [x] 查询单个签名: client->checkSingleSignature()
9 | - [x] 编辑签名: client->updateSignature()
10 | - [x] 删除签名: client->deleteSignature()
11 |
12 | - 模板管理
13 | - [x] 创建模板: client->createTemplate()
14 | - [x] 列出模板: client->queryTemplate()
15 | - [x] 查询单个模板: client->querySingleTemplate()
16 | - [x] 编辑模板: client->updateTemplate()
17 | - [x] 删除模板: client->deleteTemplate()
18 |
19 | - 发送短信
20 | - [x] 发送短信: client->sendMessage()
21 |
22 | - 查询发送记录
23 | - [x] 查询发送记录: client->querySendSms()
24 |
25 | ## Demo
26 |
27 | - 签名管理
28 | - [创建签名](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_create_signature.php)
29 | - [列出签名](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_query_signature.php)
30 | - [查询单个签名](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_query_single_signature.php)
31 | - [编辑签名](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_edit_signature.php)
32 | - [删除签名](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_delete_signature.php)
33 |
34 | - 模板管理
35 | - [创建模板](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_create_template.php)
36 | - [列出模板](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_query_template.php)
37 | - [查询单个模板](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_query_single_template.php)
38 | - [编辑模板](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_edit_template.php)
39 | - [删除模板](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_delete_template.php)
40 |
41 | - 发送短信
42 | - [发送短信](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_send_message.php)
43 |
44 | - 查询发送记录
45 | - [查询发送记录](https://github.com/qiniu/php-sdk/tree/master/examples/sms/sms_query_send_sms.php)
46 |
--------------------------------------------------------------------------------
/src/Qiniu/Processing/Operation.php:
--------------------------------------------------------------------------------
1 | auth = $auth;
26 | $this->domain = $domain;
27 | $this->token_expire = $token_expire;
28 | $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password);
29 | }
30 |
31 |
32 | /**
33 | * 对资源文件进行处理
34 | *
35 | * @param string $key 待处理的资源文件名
36 | * @param string $fops string|array fop操作,多次fop操作以array的形式传入。
37 | * eg. imageView2/1/w/200/h/200, imageMogr2/thumbnail/!75px
38 | *
39 | * @return array 文件处理后的结果及错误。
40 | *
41 | * @link http://developer.qiniu.com/docs/v6/api/reference/fop/
42 | */
43 | public function execute($key, $fops)
44 | {
45 | $url = $this->buildUrl($key, $fops);
46 | $resp = Client::get($url, array(), $this->proxy->makeReqOpt());
47 | if (!$resp->ok()) {
48 | return array(null, new Error($url, $resp));
49 | }
50 | if ($resp->json() !== null) {
51 | return array($resp->json(), null);
52 | }
53 | return array($resp->body, null);
54 | }
55 |
56 | public function buildUrl($key, $fops, $protocol = 'http')
57 | {
58 | if (is_array($fops)) {
59 | $fops = implode('|', $fops);
60 | }
61 |
62 | $url = $protocol . "://$this->domain/$key?$fops";
63 | if ($this->auth !== null) {
64 | $url = $this->auth->privateDownloadUrl($url, $this->token_expire);
65 | }
66 |
67 | return $url;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/examples/rs_asynch_fetch.php:
--------------------------------------------------------------------------------
1 | useHTTPS = true; // 接口是否使用 HTTPS 协议
17 |
18 | $bucketManager = new BucketManager($auth, $config);
19 |
20 | // 异步第三方资源抓取
21 | // 参考文档:https://developer.qiniu.com/kodo/api/4097/asynch-fetch
22 |
23 | // 需要抓取的文件 URL
24 | $url = 'http://devtools.qiniu.com/qiniu.png';
25 |
26 | //回调 URL(需要可以公网访问,并能够相应 200 OK)
27 | $callbackurl = "http://your.domain.com/upload_verify_callback.php";
28 |
29 | // 回调Body
30 | $callbackbody = '{"key":"$(key)","hash":"$(etag)","w":"$(imageInfo.width)","h":"$(imageInfo.height)"}';
31 |
32 |
33 | //---------------------------------------- demo1 ----------------------------------------
34 | // 指定抓取的文件保存到七牛云空间中的名称
35 |
36 | $key = time() . '.png';
37 | list($ret, $err) = $bucketManager->asynchFetch($url, $bucket, null, $key, null, null, $callbackurl, $callbackbody);
38 | echo "=====> asynch fetch $url to bucket: $bucket key: $key\n";
39 | if ($err !== null) {
40 | var_dump($err);
41 | } else {
42 | $id = $ret['id'];
43 | echo "id is: $id\n";
44 | }
45 |
46 | //---------------------------------------- demo2 ----------------------------------------
47 | // 不指定 key 时,以文件内容的 hash 作为文件名
48 |
49 | $key = null;
50 | list($ret, $err) = $bucketManager->asynchFetch($url, $bucket, null, $key, null, null, $callbackurl, $callbackbody);
51 | echo "=====> asynch fetch $url to bucket: $bucket key: $(etag)\n";
52 | if ($err !== null) {
53 | var_dump($err);
54 | } else {
55 | $id = $ret['id'];
56 | echo "id is: $id\n";
57 | }
58 |
59 | // 查询异步抓取的进度和状态
60 |
61 | // 华东:z0,华北:z1,华南:z2,北美:na0,东南亚:as0
62 | $zone = 'z2';
63 |
64 | sleep(10); // 由于异步抓取需要耗时,等待 10 秒后再查询状态
65 | list($ret, $err) = $bucketManager->asynchFetchStatus($zone, $id);
66 | echo "\n====> asynch fetch status: \n";
67 | if ($err != null) {
68 | var_dump($err);
69 | } else {
70 | var_dump($ret);
71 | }
72 |
--------------------------------------------------------------------------------
/src/Qiniu/Http/Middleware/RetryDomainsMiddleware.php:
--------------------------------------------------------------------------------
1 | backup domains.
11 | */
12 | private $backupDomains;
13 |
14 | /**
15 | * @var numeric max retry times for each backup domains.
16 | */
17 | private $maxRetryTimes;
18 |
19 | /**
20 | * @var callable args response and request; returns bool; If true will retry with backup domains.
21 | */
22 | private $retryCondition;
23 |
24 | /**
25 | * @param array $backupDomains
26 | * @param numeric $maxRetryTimes
27 | */
28 | public function __construct($backupDomains, $maxRetryTimes = 2, $retryCondition = null)
29 | {
30 | $this->backupDomains = $backupDomains;
31 | $this->maxRetryTimes = $maxRetryTimes;
32 | $this->retryCondition = $retryCondition;
33 | }
34 |
35 | private function shouldRetry($resp, $req)
36 | {
37 | if (is_callable($this->retryCondition)) {
38 | return call_user_func($this->retryCondition, $resp, $req);
39 | }
40 |
41 | return !$resp || $resp->needRetry();
42 | }
43 |
44 | /**
45 | * @param Request $request
46 | * @param callable(Request): Response $next
47 | * @return Response
48 | */
49 | public function send($request, $next)
50 | {
51 | $response = null;
52 | $urlComponents = parse_url($request->url);
53 |
54 | foreach (array_merge(array($urlComponents["host"]), $this->backupDomains) as $backupDomain) {
55 | $urlComponents["host"] = $backupDomain;
56 | $request->url = \Qiniu\unparse_url($urlComponents);
57 | $retriedTimes = 0;
58 |
59 | while ($retriedTimes < $this->maxRetryTimes) {
60 | $response = $next($request);
61 |
62 | $retriedTimes += 1;
63 |
64 | if (!$this->shouldRetry($response, $request)) {
65 | return $response;
66 | }
67 | }
68 | }
69 |
70 | if (!$response) {
71 | $response = $next($request);
72 | }
73 |
74 | return $response;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/.github/workflows/test-ci.yml:
--------------------------------------------------------------------------------
1 | name: PHP CI with Composer
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | strategy:
8 | fail-fast: false
9 | matrix:
10 | php-versions: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v2
15 |
16 | - name: Setup php for mock server
17 | uses: shivammathur/setup-php@v2
18 | with:
19 | php-version: '8.2'
20 |
21 | - name: Install Go
22 | uses: actions/setup-go@v2
23 | with:
24 | go-version: '1.21.x'
25 |
26 | - name: Setup build-in server
27 | run: |
28 | nohup php -S localhost:9000 -t ./tests/mock-server/ > phpd.log 2>&1 &
29 | echo $! > mock-server.pid
30 |
31 | cd tests/socks5-server/
32 | nohup go run main.go > ../../socks5.log 2>&1 &
33 | echo $! > ../../socks-server.pid
34 |
35 | - name: Setup php
36 | uses: shivammathur/setup-php@v2
37 | with:
38 | php-version: ${{ matrix.php-versions }}
39 |
40 | - name: Install dependencies
41 | run: |
42 | composer self-update
43 | composer install --no-interaction --prefer-source --dev
44 |
45 | - name: Run cases
46 | run: |
47 | ./vendor/bin/phpcs --standard=PSR2 src
48 | ./vendor/bin/phpcs --standard=PSR2 examples
49 | ./vendor/bin/phpcs --standard=PSR2 tests
50 | ./vendor/bin/phpunit --coverage-clover=coverage.xml
51 | cat mock-server.pid | xargs kill
52 | cat socks-server.pid | xargs kill
53 |
54 | env:
55 | QINIU_ACCESS_KEY: ${{ secrets.QINIU_ACCESS_KEY }}
56 | QINIU_SECRET_KEY: ${{ secrets.QINIU_SECRET_KEY }}
57 | QINIU_TEST_BUCKET: ${{ secrets.QINIU_TEST_BUCKET }}
58 | QINIU_TEST_DOMAIN: ${{ secrets.QINIU_TEST_DOMAIN }}
59 |
60 | - name: Print mock server log
61 | if: ${{ failure() }}
62 | run: |
63 | cat phpd.log
64 |
65 | - name: Print socks5 server log
66 | if: ${{ failure() }}
67 | run: |
68 | cat socks5.log
69 |
70 | - name: After_success
71 | run: bash <(curl -s https://codecov.io/bash)
72 |
--------------------------------------------------------------------------------
/examples/image_url_builder.php:
--------------------------------------------------------------------------------
1 |
29 | */
30 | $thumbLink = $imageUrlBuilder->thumbnail($url, 1, 100, 100);
31 |
32 | // 函数方式调用 也可拼接多个操作参数 图片+水印
33 | $thumbLink2 = \Qiniu\thumbnail($url2, 1, 100, 100);
34 | var_dump($thumbLink, $thumbLink2);
35 |
36 | /**
37 | * 图片水印
38 | *
39 | * @param string $url 图片链接
40 | * @param string $image 水印图片链接
41 | * @param int $dissolve 透明度 [可选]
42 | * @param string $gravity 水印位置 [可选]
43 | * @param int $dx 横轴边距 [可选]
44 | * @param int $dy 纵轴边距 [可选]
45 | * @param int $watermarkScale 自适应原图的短边比例 [可选]
46 | * @link https://developer.qiniu.com/dora/api/1316/image-watermarking-processing-watermark
47 | * @return string
48 | * @author Sherlock Ren
49 | */
50 | $waterLink = $imageUrlBuilder->waterImg($url, $waterImage);
51 | // 函数调用方法
52 | //$waterLink = \Qiniu\waterImg($url, $waterImage);
53 | var_dump($waterLink);
54 |
55 | /**
56 | * 文字水印
57 | *
58 | * @param string $url 图片链接
59 | * @param string $text 文字
60 | * @param string $font 文字字体
61 | * @param string $fontSize 文字字号
62 | * @param string $fontColor 文字颜色 [可选]
63 | * @param int $dissolve 透明度 [可选]
64 | * @param string $gravity 水印位置 [可选]
65 | * @param int $dx 横轴边距 [可选]
66 | * @param int $dy 纵轴边距 [可选]
67 | * @link http://developer.qiniu.com/code/v6/api/kodo-api/image/watermark.html#text-watermark
68 | * @return string
69 | * @author Sherlock Ren
70 | */
71 | $textLink = $imageUrlBuilder->waterText($url, '你瞅啥', '微软雅黑', 300);
72 | // 函数调用方法
73 | // $textLink = \Qiniu\waterText($url, '你瞅啥', '微软雅黑', 300);
74 | var_dump($textLink);
75 |
--------------------------------------------------------------------------------
/src/Qiniu/Etag.php:
--------------------------------------------------------------------------------
1 | uploadToken($bucket);
17 | $uploadMgr = new UploadManager();
18 |
19 | //---------------------------------------- upload demo1 ----------------------------------------
20 | // 上传字符串到七牛
21 |
22 | list($ret, $err) = $uploadMgr->put($token, null, 'content string');
23 | echo "\n====> put result: \n";
24 | if ($err !== null) {
25 | var_dump($err);
26 | } else {
27 | var_dump($ret);
28 | }
29 |
30 |
31 | //---------------------------------------- upload demo2 ----------------------------------------
32 | // 上传文件到七牛
33 |
34 | $filePath = './php-logo.png';
35 | $key = 'php-logo.png';
36 | list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath);
37 | echo "\n====> putFile result: \n";
38 | if ($err !== null) {
39 | var_dump($err);
40 | } else {
41 | var_dump($ret);
42 | }
43 |
44 |
45 | //---------------------------------------- upload demo3 ----------------------------------------
46 | // 上传文件到七牛后, 七牛将文件名和文件大小回调给业务服务器.
47 | // 可参考文档: https://developer.qiniu.com/kodo/manual/1206/put-policy
48 |
49 | $policy = array(
50 | 'callbackUrl' => 'http://172.30.251.210/upload_verify_callback.php',
51 | 'callbackBody' => 'filename=$(fname)&filesize=$(fsize)'
52 | // 'callbackBodyType' => 'application/json',
53 | // 'callbackBody' => '{"filename":$(fname), "filesize": $(fsize)}' //设置application/json格式回调
54 | );
55 | $token = $auth->uploadToken($bucket, null, 3600, $policy);
56 |
57 |
58 | list($ret, $err) = $uploadMgr->putFile($token, null, $key);
59 | echo "\n====> putFile result: \n";
60 | if ($err !== null) {
61 | var_dump($err);
62 | } else {
63 | var_dump($ret);
64 | }
65 |
66 |
67 | //---------------------------------------- upload demo4 ----------------------------------------
68 | // 上传视频,上传完成后进行 m3u8 的转码, 并给视频打水印
69 |
70 | $wmImg = Qiniu\base64_urlSafeEncode('http://devtools.qiniudn.com/qiniu.png');
71 | $pfop = "avthumb/m3u8/wmImage/$wmImg";
72 |
73 | // 转码完成后回调到业务服务器。(公网可以访问,并相应 200 OK)
74 | $notifyUrl = 'http://notify.fake.com';
75 |
76 | $policy = array(
77 | 'persistentOps' => $pfop,
78 | 'persistentNotifyUrl' => $notifyUrl,
79 | 'persistentPipeline' => $pipeline
80 | );
81 | $token = $auth->uploadToken($bucket, null, 3600, $policy);
82 | print($token);
83 | list($ret, $err) = $uploadMgr->putFile($token, null, $key);
84 | echo "\n====> putFile result: \n";
85 | if ($err !== null) {
86 | var_dump($err);
87 | } else {
88 | var_dump($ret);
89 | }
90 |
--------------------------------------------------------------------------------
/src/Qiniu/Http/RequestOptions.php:
--------------------------------------------------------------------------------
1 |
55 | */
56 | public $middlewares;
57 |
58 | public function __construct(
59 | $connection_timeout = null,
60 | $connection_timeout_ms = null,
61 | $timeout = null,
62 | $timeout_ms = null,
63 | $middlewares = array(),
64 | $proxy = null,
65 | $proxy_auth = null,
66 | $proxy_user_password = null
67 | ) {
68 | $this->connection_timeout = $connection_timeout;
69 | $this->connection_timeout_ms = $connection_timeout_ms;
70 | $this->timeout = $timeout;
71 | $this->timeout_ms = $timeout_ms;
72 | $this->proxy = $proxy;
73 | $this->proxy_auth = $proxy_auth;
74 | $this->proxy_user_password = $proxy_user_password;
75 | $this->middlewares = $middlewares;
76 | }
77 |
78 | public function getCurlOpt()
79 | {
80 | $result = array();
81 | if ($this->connection_timeout != null) {
82 | $result[CURLOPT_CONNECTTIMEOUT] = $this->connection_timeout;
83 | }
84 | if ($this->connection_timeout_ms != null) {
85 | $result[CURLOPT_CONNECTTIMEOUT_MS] = $this->connection_timeout_ms;
86 | }
87 | if ($this->timeout != null) {
88 | $result[CURLOPT_TIMEOUT] = $this->timeout;
89 | }
90 | if ($this->timeout_ms != null) {
91 | $result[CURLOPT_TIMEOUT_MS] = $this->timeout_ms;
92 | }
93 | if ($this->proxy != null) {
94 | $result[CURLOPT_PROXY] = $this->proxy;
95 | }
96 | if ($this->proxy_auth != null) {
97 | $result[CURLOPT_PROXYAUTH] = $this->proxy_auth;
98 | }
99 | if ($this->proxy_user_password != null) {
100 | $result[CURLOPT_PROXYUSERPWD] = $this->proxy_user_password;
101 | }
102 | return $result;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/EntryTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('cWluaXVwaG90b3M6Z29nb3BoZXIuanBn', $encodeEntryURI);
16 | }
17 |
18 | public function testKeyEmpty()
19 | {
20 | $bucket = 'qiniuphotos';
21 | $key = '';
22 | $encodeEntryURI = Qiniu\entry($bucket, $key);
23 | $this->assertEquals('cWluaXVwaG90b3M6', $encodeEntryURI);
24 | }
25 |
26 | public function testKeyNull()
27 | {
28 | $bucket = 'qiniuphotos';
29 | $key = null;
30 | $encodeEntryURI = Qiniu\entry($bucket, $key);
31 | $this->assertEquals('cWluaXVwaG90b3M=', $encodeEntryURI);
32 | }
33 |
34 | public function testKeyNeedReplacePlusSymbol()
35 | {
36 | $bucket = 'qiniuphotos';
37 | $key = '012ts>a';
38 | $encodeEntryURI = Qiniu\entry($bucket, $key);
39 | $this->assertEquals('cWluaXVwaG90b3M6MDEydHM-YQ==', $encodeEntryURI);
40 | }
41 |
42 | public function testKeyNeedReplaceSlashSymbol()
43 | {
44 | $bucket = 'qiniuphotos';
45 | $key = '012ts?a';
46 | $encodeEntryURI = Qiniu\entry($bucket, $key);
47 | $this->assertEquals('cWluaXVwaG90b3M6MDEydHM_YQ==', $encodeEntryURI);
48 | }
49 | public function testDecodeEntry()
50 | {
51 | $entry = 'cWluaXVwaG90b3M6Z29nb3BoZXIuanBn';
52 | list($bucket, $key) = Qiniu\decodeEntry($entry);
53 | $this->assertEquals('qiniuphotos', $bucket);
54 | $this->assertEquals('gogopher.jpg', $key);
55 | }
56 |
57 | public function testDecodeEntryWithEmptyKey()
58 | {
59 | $entry = 'cWluaXVwaG90b3M6';
60 | list($bucket, $key) = Qiniu\decodeEntry($entry);
61 | $this->assertEquals('qiniuphotos', $bucket);
62 | $this->assertEquals('', $key);
63 | }
64 |
65 | public function testDecodeEntryWithNullKey()
66 | {
67 | $entry = 'cWluaXVwaG90b3M=';
68 | list($bucket, $key) = Qiniu\decodeEntry($entry);
69 | $this->assertEquals('qiniuphotos', $bucket);
70 | $this->assertNull($key);
71 | }
72 |
73 | public function testDecodeEntryWithPlusSymbol()
74 | {
75 | $entry = 'cWluaXVwaG90b3M6MDEydHM-YQ==';
76 | list($bucket, $key) = Qiniu\decodeEntry($entry);
77 | $this->assertEquals('qiniuphotos', $bucket);
78 | $this->assertEquals('012ts>a', $key);
79 | }
80 |
81 | public function testDecodeEntryWithSlashSymbol()
82 | {
83 | $entry = 'cWluaXVwaG90b3M6MDEydHM_YQ==';
84 | list($bucket, $key) = Qiniu\decodeEntry($entry);
85 | $this->assertEquals('qiniuphotos', $bucket);
86 | $this->assertEquals('012ts?a', $key);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Qiniu Cloud SDK for PHP
2 | [](LICENSE)
3 | [](https://travis-ci.org/qiniu/php-sdk)
4 | [](https://github.com/qiniu/php-sdk/releases)
5 | [](https://packagist.org/packages/qiniu/php-sdk)
6 | [](https://packagist.org/packages/qiniu/php-sdk)
7 | [](https://scrutinizer-ci.com/g/qiniu/php-sdk/?branch=master)
8 | [](https://codecov.io/gh/qiniu/php-sdk)
9 | [](https://gitter.im/qiniu/php-sdk?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
10 | [](http://weibo.com/qiniutek)
11 |
12 |
13 | ## 安装
14 |
15 | 推荐使用 `composer` 进行安装。可以使用 composer.json 声明依赖,或者运行下面的命令。SDK 包已经放到这里 [`qiniu/php-sdk`][install-packagist] 。
16 |
17 | ```bash
18 | $ composer require qiniu/php-sdk
19 | ```
20 |
21 | ## 运行环境
22 |
23 | | Qiniu SDK版本 | PHP 版本 |
24 | |:--------------------:|:-----------------------------------------------:|
25 | | 7.x | cURL extension, 5.3 - 5.6, 7.0 - 7.4, 8.0-8.1 |
26 | | 6.x | cURL extension, 5.2 - 5.6 |
27 |
28 | ## 使用方法
29 |
30 | ### 上传
31 | ```php
32 | use Qiniu\Storage\UploadManager;
33 | use Qiniu\Auth;
34 | ...
35 | $uploadMgr = new UploadManager();
36 | $auth = new Auth($accessKey, $secretKey);
37 | $token = $auth->uploadToken($bucket);
38 | list($ret, $error) = $uploadMgr->putFile($token, 'key', 'filePath');
39 | ...
40 | ```
41 |
42 | ## 测试
43 |
44 | ``` bash
45 | $ ./vendor/bin/phpunit tests/Qiniu/Tests/
46 | ```
47 |
48 | ## 常见问题
49 |
50 | - `$error` 保留了请求响应的信息,失败情况下 `ret` 为 `none`, 将 `$error` 可以打印出来,提交给我们。
51 | - API 的使用 demo 可以参考 [examples](https://github.com/qiniu/php-sdk/tree/master/examples)。
52 |
53 | ## 代码贡献
54 |
55 | 详情参考[代码提交指南](https://github.com/qiniu/php-sdk/blob/master/CONTRIBUTING.md)。
56 |
57 | ## 贡献记录
58 |
59 | - [所有贡献者](https://github.com/qiniu/php-sdk/contributors)
60 |
61 | ## 联系我们
62 |
63 | - 如果需要帮助,请提交工单(在portal右侧点击咨询和建议提交工单,或者直接向 support@qiniu.com 发送邮件)
64 | - 如果有什么问题,可以到问答社区提问,[问答社区](https://qiniu.segmentfault.com/)
65 | - 更详细的文档,见[官方文档站](https://developer.qiniu.com/)
66 | - 如果发现了 bug, 欢迎提交 [issue](https://github.com/qiniu/php-sdk/issues)
67 | - 如果有功能需求,欢迎提交 [issue](https://github.com/qiniu/php-sdk/issues)
68 | - 如果要提交代码,欢迎提交 pull request
69 | - 欢迎关注我们的[微信](https://www.qiniu.com/#weixin) [微博](https://weibo.com/qiniutek),及时获取动态信息。
70 |
71 | ## 代码许可
72 |
73 | The MIT License (MIT).详情见 [License文件](https://github.com/qiniu/php-sdk/blob/master/LICENSE).
74 |
75 | [packagist]: http://packagist.org
76 | [install-packagist]: https://packagist.org/packages/qiniu/php-sdk
77 |
--------------------------------------------------------------------------------
/examples/upload_tokens.php:
--------------------------------------------------------------------------------
1 | uploadToken($bucket, null, $expires, $policy, true);
21 | print($upToken . "\n");
22 |
23 | //---------------------------------------- demo2 ----------------------------------------
24 | // 自定义凭证有效期(示例2小时)
25 |
26 | $expires = 7200;
27 | $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
28 | print($upToken . "\n");
29 |
30 | //---------------------------------------- demo3 ----------------------------------------
31 | // 覆盖上传凭证
32 |
33 | $expires = 3600;
34 | $keyToOverwrite = 'qiniu.mp4';
35 | $upToken = $auth->uploadToken($bucket, $keyToOverwrite, $expires, $policy, true);
36 | print($upToken . "\n");
37 |
38 | //---------------------------------------- demo4 ----------------------------------------
39 | // 自定义上传回复(非callback模式)凭证
40 |
41 | $returnBody = '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}';
42 | $policy = array(
43 | 'returnBody' => $returnBody
44 | );
45 | $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
46 | print($upToken . "\n");
47 |
48 | //---------------------------------------- demo5 ----------------------------------------
49 | // 带回调业务服务器的凭证(application/json)
50 |
51 | $policy = array(
52 | 'callbackUrl' => 'http://api.example.com/qiniu/upload/callback',
53 | 'callbackBody' => '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}',
54 | 'callbackBodyType' => 'application/json'
55 | );
56 | $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
57 | print($upToken . "\n");
58 |
59 | //---------------------------------------- demo6 ----------------------------------------
60 | // 带回调业务服务器的凭证(application/x-www-form-urlencoded)
61 |
62 | $policy = array(
63 | 'callbackUrl' => 'http://api.example.com/qiniu/upload/callback',
64 | 'callbackBody' => 'key=$(key)&hash=$(etag)&bucket=$(bucket)&fsize=$(fsize)&name=$(x:name)'
65 | );
66 | $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
67 | print($upToken . "\n");
68 |
69 | //---------------------------------------- demo7 ----------------------------------------
70 | // 带数据处理的凭证
71 |
72 | $saveMp4Entry = \Qiniu\base64_urlSafeEncode($bucket . ":avthumb_test_target.mp4");
73 | $saveJpgEntry = \Qiniu\base64_urlSafeEncode($bucket . ":vframe_test_target.jpg");
74 | $avthumbMp4Fop = "avthumb/mp4|saveas/" . $saveMp4Entry;
75 | $vframeJpgFop = "vframe/jpg/offset/1|saveas/" . $saveJpgEntry;
76 | $policy = array(
77 | 'persistentOps' => $avthumbMp4Fop . ";" . $vframeJpgFop,
78 | 'persistentPipeline' => "video-pipe",
79 | 'persistentNotifyUrl' => "http://api.example.com/qiniu/pfop/notify",
80 | );
81 | $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
82 | print($upToken . "\n");
83 |
--------------------------------------------------------------------------------
/src/Qiniu/Storage/ArgusManager.php:
--------------------------------------------------------------------------------
1 | auth = $auth;
31 | if ($config == null) {
32 | $this->config = new Config();
33 | } else {
34 | $this->config = $config;
35 | }
36 | $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password);
37 | }
38 |
39 | /**
40 | * 视频审核
41 | *
42 | * @param string $body body信息
43 | *
44 | * @return array 成功返回NULL,失败返回对象Qiniu\Http\Error
45 | * @link https://developer.qiniu.com/censor/api/5620/video-censor
46 | */
47 | public function censorVideo($body)
48 | {
49 | $path = '/v3/video/censor';
50 |
51 | return $this->arPost($path, $body);
52 | }
53 |
54 |
55 | /**
56 | * 图片审核
57 | *
58 | * @param string $body
59 | *
60 | * @return array 成功返回NULL,失败返回对象Qiniu\Http\Error
61 | * @link https://developer.qiniu.com/censor/api/5588/image-censor
62 | */
63 | public function censorImage($body)
64 | {
65 | $path = '/v3/image/censor';
66 |
67 | return $this->arPost($path, $body);
68 | }
69 |
70 | /**
71 | * 查询视频审核结果
72 | *
73 | * @param string $jobid 任务ID
74 | * @return array
75 | * @link https://developer.qiniu.com/censor/api/5620/video-censor
76 | */
77 | public function censorStatus($jobid)
78 | {
79 | $scheme = "http://";
80 |
81 | if ($this->config->useHTTPS === true) {
82 | $scheme = "https://";
83 | }
84 | $url = $scheme . Config::ARGUS_HOST . "/v3/jobs/video/$jobid";
85 | $response = $this->get($url);
86 | if (!$response->ok()) {
87 | return array(null, new Error($url, $response));
88 | }
89 | return array($response->json(), null);
90 | }
91 |
92 | private function getArHost()
93 | {
94 | $scheme = "http://";
95 | if ($this->config->useHTTPS === true) {
96 | $scheme = "https://";
97 | }
98 | return $scheme . Config::ARGUS_HOST;
99 | }
100 |
101 | private function arPost($path, $body = null)
102 | {
103 | $url = $this->getArHost() . $path;
104 | return $this->post($url, $body);
105 | }
106 |
107 | private function get($url)
108 | {
109 | $headers = $this->auth->authorizationV2($url, 'GET');
110 |
111 | return Client::get($url, $headers, $this->proxy->makeReqOpt());
112 | }
113 |
114 | private function post($url, $body)
115 | {
116 | $headers = $this->auth->authorizationV2($url, 'POST', $body, 'application/json');
117 | $headers['Content-Type'] = 'application/json';
118 | $ret = Client::post($url, $body, $headers, $this->proxy->makeReqOpt());
119 | if (!$ret->ok()) {
120 | return array(null, new Error($url, $ret));
121 | }
122 | $r = ($ret->body === null) ? array() : $ret->json();
123 | if (strstr($url, "video")) {
124 | $jobid = $r['job'];
125 | return array($jobid, null);
126 | }
127 | return array($r, null);
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/ConfigTest.php:
--------------------------------------------------------------------------------
1 | accessKey = $accessKey;
21 | global $bucketName;
22 | $this->bucketName = $bucketName;
23 | }
24 |
25 | public function testGetApiHost()
26 | {
27 | $conf = new Config();
28 | $hasException = false;
29 | $apiHost = '';
30 | try {
31 | $apiHost = $conf->getApiHost($this->accessKey, $this->bucketName);
32 | } catch (\Exception $e) {
33 | $hasException = true;
34 | }
35 | $this->assertFalse($hasException);
36 | }
37 |
38 | public function testGetApiHostErrored()
39 | {
40 | $conf = new Config();
41 | $hasException = false;
42 | try {
43 | $conf->getApiHost($this->accessKey, "fakebucket");
44 | } catch (\Exception $e) {
45 | $hasException = true;
46 | }
47 | $this->assertTrue($hasException);
48 | }
49 |
50 | public function testGetApiHostV2()
51 | {
52 | $conf = new Config();
53 | list($apiHost, $err) = $conf->getApiHostV2($this->accessKey, $this->bucketName);
54 | $this->assertNull($err);
55 | }
56 |
57 | public function testGetApiHostV2Errored()
58 | {
59 | $conf = new Config();
60 | list($apiHost, $err) = $conf->getApiHostV2($this->accessKey, "fakebucket");
61 | $this->assertNotNull($err->code());
62 | $this->assertEquals(631, $err->code());
63 | $this->assertNull($apiHost);
64 | }
65 |
66 | public function testSetUcHost()
67 | {
68 | $conf = new Config();
69 | $this->assertEquals('http://' . Config::UC_HOST, $conf->getUcHost());
70 | $conf->setUcHost("uc.example.com");
71 | $this->assertEquals("http://uc.example.com", $conf->getUcHost());
72 |
73 | $conf = new Config();
74 | $conf->useHTTPS = true;
75 | $this->assertEquals('https://' . Config::UC_HOST, $conf->getUcHost());
76 | $conf->setUcHost("uc.example.com");
77 | $this->assertEquals("https://uc.example.com", $conf->getUcHost());
78 | }
79 |
80 | public function testGetRegionWithCustomDomain()
81 | {
82 | $conf = new Config();
83 | $conf->setQueryRegionHost(
84 | "uc.qbox.me"
85 | );
86 | list(, $err) = $conf->getRsHostV2($this->accessKey, $this->bucketName);
87 | $this->assertNull($err);
88 | }
89 |
90 | public function testGetRegionWithBackupDomains()
91 | {
92 | $conf = new Config();
93 | $conf->setQueryRegionHost(
94 | "fake-uc.phpsdk.qiniu.com",
95 | array(
96 | "unavailable-uc.phpsdk.qiniu.com",
97 | Config::UC_HOST // real uc
98 | )
99 | );
100 | list(, $err) = $conf->getRsHostV2($this->accessKey, $this->bucketName);
101 | $this->assertNull($err);
102 | }
103 |
104 | public function testGetRegionWithUcAndBackupDomains()
105 | {
106 | $conf = new Config();
107 | $conf->setUcHost("fake-uc.phpsdk.qiniu.com");
108 | $conf->setBackupQueryRegionHosts(
109 | array(
110 | "unavailable-uc.phpsdk.qiniu.com",
111 | Config::UC_HOST // real uc
112 | )
113 | );
114 | list(, $err) = $conf->getRsHostV2($this->accessKey, $this->bucketName);
115 | $this->assertNull($err);
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 7.14.0 (2024-10-16)
4 | * 对象存储,持久化处理支持工作流模版
5 |
6 | ## 7.13.0 (2024-09-05)
7 | * 对象存储,验证回调方法新增支持 Qiniu 签名
8 | * 对象存储,调整查询空间区域域名顺序与默认空间管理域名
9 | * 支持闲时任务配置
10 |
11 | ## 7.12.1 (2024-02-21)
12 | * 对象存储,添加上传策略部分字段
13 |
14 | ## 7.12.0 (2023-12-11)
15 | * 对象存储,支持归档直读存储
16 | * 对象存储,批量操作支持自动查询 rs 服务域名
17 |
18 | ## 7.11.0 (2023-09-05)
19 | * 支持代理
20 |
21 | ## 7.10.1 (2023-08-04)
22 | * 修复部分 API 调用中间件合并失败(#417)
23 |
24 | ## 7.10.0 (2023-06-20)
25 | * 对象存储,新增请求中间件逻辑,方便拓展请求逻辑
26 | * 对象存储,新增备用 UC 域名用于查询区域域名
27 | * 对象存储,修复分片上传初始化失败无法快速失败
28 | * 对象存储,移除首尔区域
29 |
30 | ## 7.9.0 (2023-03-31)
31 | * 对象存储,修复无法对 key 为空字符串的对象进行操作
32 | * 修复 301 重定向无法正确获取 header 信息
33 | * 对象存储,新增查询区域域名过期时间
34 | * 对象存储,更新获取区域域名的接口
35 | * 对象存储,更新查询 bucket 域名为 uc 服务
36 | * 对象存储,新增 uc 服务可配置
37 |
38 | ## 7.8.0 (2022-10-25)
39 | * 移除不推荐域名,并增加区域亚太-首尔和华东-浙江2
40 | * 对象存储,修复断点上传的文件内容不正确
41 | * 对象存储,优化分片上传 ctx 超时检测
42 |
43 | ## 7.7.0 (2022-09-02)
44 | * 对象存储,新增支持设置文件级别生命周期 setObjectLifecycle API
45 | * 对象存储,内置增加七牛新建存储区域域名信息
46 | * 修复当前已知问题
47 |
48 | ## 7.6.0 (2022-06-08)
49 | * 对象存储,管理类 API 发送请求时增加 [X-Qiniu-Date](https://developer.qiniu.com/kodo/3924/common-request-headers) (生成请求的时间) header
50 |
51 |
52 | ## 7.5.0 (2022-04-18)
53 | * 对象存储,新增支持 [深度归档存储类型](https://developer.qiniu.com/kodo/3956/kodo-category#deep_archive)
54 |
55 | ## 7.4.3 (2022-04-01)
56 | * 优化签名算法逻辑
57 |
58 | ## 7.4.2(2022-03-01)
59 | * 修复已知关于请求 Header 处理不当问题,比如没有处理为大小写不敏感等问题
60 |
61 | ## 7.4.1(2021-09-24)
62 | * 修复了 分片上传 v2 已知问题,明确给出了参数不合理情况下对应的错误提示信息
63 |
64 | ## 7.4.0 (2021-07-19)
65 | * 【对象存储】支持 [分片上传 v2](https://developer.qiniu.com/kodo/7458/multipartupload) 和 断点续传,使用方式见 [开发者文档](https://developer.qiniu.com/kodo/1241/php#resume-upload-file)
66 |
67 | ## 7.3.0 (2020-09-24)
68 | ### 新增
69 | * 【对象存储】增加异步抓取方法与demo
70 | * 【融合cdn】增加查询CDN刷新记录、查询CDN预取记录方法与demo
71 | * 【云短信】增加查询短信发送记录的方法
72 | * 【实时音视频】增加rtc停止房间的合流转推方法
73 | * 【内容审核】增加图片审核、视频审核方法与demo
74 |
75 | ### 修复
76 | * 【对象存储】修复签算 token 时上传策略中的 forceSaveKey 字段不生效的问题
77 | * 【对象存储】修复更新空间事件通知规则方法
78 |
79 | ### 优化
80 | * 【对象存储】创建空间迁移到mkbucketv3 api
81 | * 优化对 http2 返回头的判断
82 | * 优化 demo 中的文档注释说明
83 | * docs 目录下的 rtc demo 移动至 examples/rtc 目录下
84 | * docs 目录下的 sms demo 移动至 examples/sms 目录下
85 |
86 | ## 7.2.10 (2019-10-28)
87 | * 去除云短信类类型指定
88 | * 修改不传文件名时存在表单上传错误的情况
89 |
90 | ## 7.2.9 (2019-07-09)
91 | * 添加空间管理、云短信接口
92 | * 去除无效参数
93 |
94 | ## 7.2.7 (2018-11-06)
95 | * 添加 QVM 内网上传到 KODO 的 zone 设置
96 |
97 | ## 7.2.6 (2018-05-18)
98 | * 修复rs,rsf在不同机房默认的https域名
99 |
100 | ## 7.2.5 (2018-05-10)
101 | * 修复表单上传中多余的参数checkCrc导致的fname错位问题
102 |
103 | ## 7.2.4 (2018-05-09)
104 | ### 增加
105 | * 连麦功能
106 |
107 | ## 7.2.3 (2018-01-20)
108 | ### 增加
109 | * 新加坡机房
110 | ### 修正
111 | * 获取域名的入口域名
112 | * http回复头部兼容大小写
113 |
114 | ## 7.2.2 (2017-11-06)
115 | ### 增加
116 | * Qiniu算法的鉴权方法
117 |
118 | ## 7.1.4 (2017-06-21)
119 | ### 增加
120 | * cdn 文件/目录 刷新
121 | * cdn 获取 流量/带宽
122 | * cdn 获取域名的访问日志列表
123 | * cdn 对资源链接进行时间戳防盗链签名
124 |
125 | ## 7.1.3 (2016-11-18)
126 | ### 增加
127 | * move, copy操作增加force参数
128 |
129 | ## 7.1.2 (2016-11-12)
130 | ### 修正
131 | * 明确抛出获取各区域域名失败时的报错
132 |
133 | ## 7.1.1 (2016-11-02)
134 | ### 修正
135 | * 多区域配置文件存储目录从home修改到tmp目录
136 |
137 |
138 | ## 7.1.0 (2016-10-22)
139 | ### 增加
140 | * 多存储区域的支持
141 |
142 | ## 7.0.8 (2016-07-19)
143 | ### 增加
144 | * demo
145 | * https url 支持
146 | * deleteAfterDays 策略
147 | * 添加图片处理链接统一拼接方法 by @SherlockRen
148 |
149 | ## 7.0.7 (2016-01-12)
150 | ### 修正
151 | * PersistentFop参数pipeline和notify_url失效
152 | * resume 模式 close file inputstream
153 |
154 | ## 7.0.6 (2015-12-05)
155 | ### 修正
156 | * php7.0 Json 对空字符串解析单元测试报错
157 | * 开启安全模式或者设置可操作目录树时,设置CURLOPT_FOLLOWLOCATION报错, by @twocabbages
158 | * fetch 支持不指定key, by @sinkcup
159 |
160 | ## 7.0.5 (2015-10-29)
161 | ### 增加
162 | * 增加上传策略最小文件大小限制 fsizeMin
163 | * 增加常见examples
164 |
165 | ## 7.0.4 (2015-07-23)
166 | ### 修正
167 | * 一些地方的严格比较检查
168 | * resumeupload 备用地址失效
169 |
170 | ## 7.0.3 (2015-07-10)
171 | ### 修改
172 | * 多zone 支持
173 |
174 | ## 7.0.2 (2015-04-18)
175 | ### 修改
176 | * fetch 接口返回内容调整
177 | * pfop 接口调整
178 |
179 | ###修正
180 | * exception 类调用
181 |
182 | ## 7.0.1 (2015-03-27)
183 | ### 增加
184 | * 增加代码注释
185 |
186 | ## 7.0.0 (2015-02-03)
187 |
188 | ### 增加
189 | * 简化上传接口
190 | * 自动选择断点续上传还是直传
191 | * 重构代码,接口和内部结构更清晰
192 | * 改变mime
193 | * 代码覆盖度报告
194 | * policy改为array, 便于灵活增加,并加入过期字段检查
195 | * 文件列表支持目录形式
196 | * 利用元编程方式支持 fop 和 pfop
197 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/ZoneTest.php:
--------------------------------------------------------------------------------
1 | bucketName = $bucketName;
29 |
30 | global $bucketNameBC;
31 | $this->bucketNameBC = $bucketNameBC;
32 |
33 | global $bucketNameNA;
34 | $this->bucketNameNA = $bucketNameNA;
35 |
36 | global $bucketNameFS;
37 | $this->bucketNameFS = $bucketNameFS;
38 |
39 | global $bucketNameAS;
40 | $this->bucketNameAS = $bucketNameAS;
41 |
42 | global $accessKey;
43 | $this->ak = $accessKey;
44 |
45 | $this->zone = new Zone();
46 | $this->zoneHttps = new Zone('https');
47 | }
48 |
49 | public function testUpHosts()
50 | {
51 | list($ret, $err) = Zone::queryZone($this->ak, 'fakebucket');
52 | $this->assertNull($ret);
53 | $this->assertNotNull($err);
54 |
55 | $zone = Zone::queryZone($this->ak, $this->bucketName);
56 | $this->assertContains('upload.qiniup.com', $zone->cdnUpHosts);
57 |
58 | $zone = Zone::queryZone($this->ak, $this->bucketNameBC);
59 | $this->assertContains('upload-z1.qiniup.com', $zone->cdnUpHosts);
60 |
61 | $zone = Zone::queryZone($this->ak, $this->bucketNameFS);
62 | $this->assertContains('upload-z2.qiniup.com', $zone->cdnUpHosts);
63 |
64 | $zone = Zone::queryZone($this->ak, $this->bucketNameNA);
65 | $this->assertContains('upload-na0.qiniup.com', $zone->cdnUpHosts);
66 |
67 | $zone = Zone::queryZone($this->ak, $this->bucketNameAS);
68 | $this->assertContains('upload-as0.qiniup.com', $zone->cdnUpHosts);
69 | }
70 |
71 | public function testIoHosts()
72 | {
73 | $zone = Zone::queryZone($this->ak, $this->bucketName);
74 | $this->assertEquals($zone->iovipHost, 'iovip.qbox.me');
75 |
76 | $zone = Zone::queryZone($this->ak, $this->bucketNameBC);
77 | $this->assertEquals($zone->iovipHost, 'iovip-z1.qbox.me');
78 |
79 | $zone = Zone::queryZone($this->ak, $this->bucketNameFS);
80 | $this->assertEquals($zone->iovipHost, 'iovip-z2.qbox.me');
81 |
82 | $zone = Zone::queryZone($this->ak, $this->bucketNameNA);
83 | $this->assertEquals($zone->iovipHost, 'iovip-na0.qbox.me');
84 |
85 | $zone = Zone::queryZone($this->ak, $this->bucketNameAS);
86 | $this->assertEquals($zone->iovipHost, 'iovip-as0.qbox.me');
87 | }
88 |
89 | public function testZonez0()
90 | {
91 | $zone = Zone::zonez0();
92 | $this->assertContains('upload.qiniup.com', $zone->cdnUpHosts);
93 | }
94 |
95 | public function testZonez1()
96 | {
97 | $zone = Zone::zonez1();
98 | $this->assertContains('upload-z1.qiniup.com', $zone->cdnUpHosts);
99 | }
100 |
101 | public function testZonez2()
102 | {
103 | $zone = Zone::zonez2();
104 | $this->assertContains('upload-z2.qiniup.com', $zone->cdnUpHosts);
105 | }
106 |
107 | public function testZoneCnEast2()
108 | {
109 | $zone = Zone::zoneCnEast2();
110 | $this->assertContains('upload-cn-east-2.qiniup.com', $zone->cdnUpHosts);
111 | }
112 |
113 | public function testZoneNa0()
114 | {
115 | $zone = Zone::zoneNa0();
116 | $this->assertContains('upload-na0.qiniup.com', $zone->cdnUpHosts);
117 | }
118 |
119 | public function testZoneAs0()
120 | {
121 | $zone = Zone::zoneAs0();
122 | $this->assertContains('upload-as0.qiniup.com', $zone->cdnUpHosts);
123 | }
124 |
125 | public function testQvmZonez0()
126 | {
127 | $zone = Zone::qvmZonez0();
128 | $this->assertContains('free-qvm-z0-xs.qiniup.com', $zone->srcUpHosts);
129 | }
130 |
131 | public function testQvmZonez1()
132 | {
133 | $zone = Zone::qvmZonez1();
134 | $this->assertContains('free-qvm-z1-zz.qiniup.com', $zone->srcUpHosts);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/src/Qiniu/Processing/PersistentFop.php:
--------------------------------------------------------------------------------
1 | auth = $auth;
37 | if ($config == null) {
38 | $this->config = new Config();
39 | } else {
40 | $this->config = $config;
41 | }
42 | $this->proxy = new Proxy($proxy, $proxy_auth, $proxy_user_password);
43 | }
44 |
45 | /**
46 | * 对资源文件进行异步持久化处理
47 | * @param string $bucket 资源所在空间
48 | * @param string $key 待处理的源文件
49 | * @param string|array $fops 待处理的pfop操作,多个pfop操作以array的形式传入。
50 | * eg. avthumb/mp3/ab/192k, vframe/jpg/offset/7/w/480/h/360
51 | * @param string $pipeline 资源处理队列
52 | * @param string $notify_url 处理结果通知地址
53 | * @param bool $force 是否强制执行一次新的指令
54 | * @param int $type 为 `1` 时开启闲时任务
55 | *
56 | *
57 | * @return array 返回持久化处理的 persistentId 与可能出现的错误。
58 | *
59 | * @link http://developer.qiniu.com/docs/v6/api/reference/fop/
60 | */
61 | public function execute(
62 | $bucket,
63 | $key,
64 | $fops = null,
65 | $pipeline = null,
66 | $notify_url = null,
67 | $force = false,
68 | $type = null,
69 | $workflow_template_id = null
70 | ) {
71 | if (is_array($fops)) {
72 | $fops = implode(';', $fops);
73 | }
74 |
75 | if (!$fops && !$workflow_template_id) {
76 | throw new \InvalidArgumentException('Must provide one of fops or template_id');
77 | }
78 |
79 | $params = array('bucket' => $bucket, 'key' => $key);
80 | \Qiniu\setWithoutEmpty($params, 'fops', $fops);
81 | \Qiniu\setWithoutEmpty($params, 'pipeline', $pipeline);
82 | \Qiniu\setWithoutEmpty($params, 'notifyURL', $notify_url);
83 | \Qiniu\setWithoutEmpty($params, 'type', $type);
84 | \Qiniu\setWithoutEmpty($params, 'workflowTemplateID', $workflow_template_id);
85 | if ($force) {
86 | $params['force'] = 1;
87 | }
88 | $data = http_build_query($params);
89 | $scheme = "http://";
90 | if ($this->config->useHTTPS === true) {
91 | $scheme = "https://";
92 | }
93 | $apiHost = $this->getApiHost();
94 | $url = $scheme . $apiHost . '/pfop/';
95 | $headers = $this->auth->authorization($url, $data, 'application/x-www-form-urlencoded');
96 | $headers['Content-Type'] = 'application/x-www-form-urlencoded';
97 | $response = Client::post($url, $data, $headers, $this->proxy->makeReqOpt());
98 | if (!$response->ok()) {
99 | return array(null, new Error($url, $response));
100 | }
101 | $r = $response->json();
102 | $id = $r['persistentId'];
103 | return array($id, null);
104 | }
105 |
106 | /**
107 | * @param string $id
108 | * @return array 返回任务状态与可能出现的错误
109 | */
110 | public function status($id)
111 | {
112 | $scheme = "http://";
113 |
114 | if ($this->config->useHTTPS === true) {
115 | $scheme = "https://";
116 | }
117 | $apiHost = $this->getApiHost();
118 | $url = $scheme . $apiHost . "/status/get/prefop?id=$id";
119 | $response = Client::get($url, array(), $this->proxy->makeReqOpt());
120 | if (!$response->ok()) {
121 | return array(null, new Error($url, $response));
122 | }
123 | return array($response->json(), null);
124 | }
125 |
126 | private function getApiHost()
127 | {
128 | if (!empty($this->config->zone) && !empty($this->config->zone->apiHost)) {
129 | $apiHost = $this->config->zone->apiHost;
130 | } else {
131 | $apiHost = Config::API_HOST;
132 | }
133 | return $apiHost;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/MiddlewareTest.php:
--------------------------------------------------------------------------------
1 |
18 | */
19 | private $orderRecorder;
20 |
21 | /**
22 | * @var string
23 | */
24 | private $label;
25 |
26 | public function __construct(&$orderRecorder, $label)
27 | {
28 | $this->orderRecorder =& $orderRecorder;
29 | $this->label = $label;
30 | }
31 |
32 | public function send($request, $next)
33 | {
34 | $this->orderRecorder[] = "bef_" . $this->label . count($this->orderRecorder);
35 | $response = $next($request);
36 | $this->orderRecorder[] = "aft_" . $this->label . count($this->orderRecorder);
37 | return $response;
38 | }
39 | }
40 |
41 | class MiddlewareTest extends TestCase
42 | {
43 | public function testSendWithMiddleware()
44 | {
45 | $orderRecorder = array();
46 |
47 | $reqOpt = new RequestOptions();
48 | $reqOpt->middlewares = array(
49 | new RecorderMiddleware($orderRecorder, "A"),
50 | new RecorderMiddleware($orderRecorder, "B")
51 | );
52 |
53 | $request = new Request(
54 | "GET",
55 | "http://localhost:9000/ok.php",
56 | array(),
57 | null,
58 | $reqOpt
59 | );
60 | $response = Client::sendRequestWithMiddleware($request);
61 |
62 | $expectRecords = array(
63 | "bef_A0",
64 | "bef_B1",
65 | "aft_B2",
66 | "aft_A3"
67 | );
68 |
69 | $this->assertEquals($expectRecords, $orderRecorder);
70 | $this->assertEquals(200, $response->statusCode);
71 | }
72 |
73 | public function testSendWithRetryDomains()
74 | {
75 | $orderRecorder = array();
76 |
77 | $reqOpt = new RequestOptions();
78 | $reqOpt->middlewares = array(
79 | new Middleware\RetryDomainsMiddleware(
80 | array(
81 | "unavailable.phpsdk.qiniu.com",
82 | "localhost:9000",
83 | ),
84 | 3
85 | ),
86 | new RecorderMiddleware($orderRecorder, "rec")
87 | );
88 |
89 | $request = new Request(
90 | "GET",
91 | "http://fake.phpsdk.qiniu.com/ok.php",
92 | array(),
93 | null,
94 | $reqOpt
95 | );
96 | $response = Client::sendRequestWithMiddleware($request);
97 |
98 | $expectRecords = array(
99 | // 'fake.phpsdk.qiniu.com' with retried 3 times
100 | 'bef_rec0',
101 | 'aft_rec1',
102 | 'bef_rec2',
103 | 'aft_rec3',
104 | 'bef_rec4',
105 | 'aft_rec5',
106 |
107 | // 'unavailable.pysdk.qiniu.com' with retried 3 times
108 | 'bef_rec6',
109 | 'aft_rec7',
110 | 'bef_rec8',
111 | 'aft_rec9',
112 | 'bef_rec10',
113 | 'aft_rec11',
114 |
115 | // 'qiniu.com' and it's success
116 | 'bef_rec12',
117 | 'aft_rec13'
118 | );
119 |
120 | $this->assertEquals($expectRecords, $orderRecorder);
121 | $this->assertEquals(200, $response->statusCode);
122 | }
123 |
124 | public function testSendFailFastWithRetryDomains()
125 | {
126 | $orderRecorder = array();
127 |
128 | $reqOpt = new RequestOptions();
129 | $reqOpt->middlewares = array(
130 | new Middleware\RetryDomainsMiddleware(
131 | array(
132 | "unavailable.phpsdk.qiniu.com",
133 | "localhost:9000",
134 | ),
135 | 3,
136 | function () {
137 | return false;
138 | }
139 | ),
140 | new RecorderMiddleware($orderRecorder, "rec")
141 | );
142 |
143 | $request = new Request(
144 | "GET",
145 | "http://fake.phpsdk.qiniu.com/ok.php",
146 | array(),
147 | null,
148 | $reqOpt
149 | );
150 | $response = Client::sendRequestWithMiddleware($request);
151 |
152 | $expectRecords = array(
153 | // 'fake.phpsdk.qiniu.com' will fail fast
154 | 'bef_rec0',
155 | 'aft_rec1'
156 | );
157 | $this->assertEquals($expectRecords, $orderRecorder);
158 | $this->assertEquals(-1, $response->statusCode);
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/CdnManagerTest.php:
--------------------------------------------------------------------------------
1 | cdnManager = new CdnManager($testAuth);
36 |
37 | global $timestampAntiLeechEncryptKey;
38 | $this->encryptKey = $timestampAntiLeechEncryptKey;
39 |
40 | global $testStartDate;
41 | $this->testStartDate = $testStartDate;
42 |
43 | global $testEndDate;
44 | $this->testEndDate = $testEndDate;
45 |
46 | global $testGranularity;
47 | $this->testGranularity = $testGranularity;
48 |
49 | global $testLogDate;
50 | $this->testLogDate = $testLogDate;
51 |
52 | global $customDomain;
53 | $this->refreshUrl = $customDomain . '/sdktest.png';
54 | $this->refreshDirs = $customDomain;
55 | $this->customDomain = $customDomain;
56 |
57 | global $customDomain2;
58 | $this->customDomain2 = $customDomain2;
59 | }
60 |
61 | public function testRefreshUrls()
62 | {
63 | list($ret, $err) = $this->cdnManager->refreshUrls(array($this->refreshUrl));
64 | $this->assertNull($err);
65 | $this->assertNotNull($ret);
66 | }
67 |
68 | public function testRefreshDirs()
69 | {
70 | list($ret, $err) = $this->cdnManager->refreshDirs(array($this->refreshDirs));
71 | $this->assertNull($err);
72 | $this->assertNotNull($ret);
73 | }
74 |
75 | public function testRefreshUrlsAndDirs()
76 | {
77 | list($ret, $err) = $this->cdnManager->refreshUrlsAndDirs(array($this->refreshUrl), array($this->refreshDirs));
78 | $this->assertNull($err);
79 | $this->assertNotNull($ret);
80 | }
81 |
82 | public function testGetCdnRefreshList()
83 | {
84 | list($ret, $err) = $this->cdnManager->getCdnRefreshList(null, null, null, 'success');
85 | $this->assertNull($err);
86 | $this->assertNotNull($ret);
87 | }
88 |
89 | public function testPrefetchUrls()
90 | {
91 | list($ret, $err) = $this->cdnManager->prefetchUrls(array($this->refreshUrl));
92 | $this->assertNull($err);
93 | $this->assertNotNull($ret);
94 | }
95 |
96 | public function testGetCdnPrefetchList()
97 | {
98 | list($ret, $err) = $this->cdnManager->getCdnPrefetchList(null, null, 'success');
99 | $this->assertNull($err);
100 | $this->assertNotNull($ret);
101 | }
102 |
103 | public function testGetBandwidthData()
104 | {
105 | list($ret, $err) = $this->cdnManager->getBandwidthData(
106 | array($this->customDomain2),
107 | $this->testStartDate,
108 | $this->testEndDate,
109 | $this->testGranularity
110 | );
111 | $this->assertNull($err);
112 | $this->assertNotNull($ret);
113 | }
114 |
115 | public function testGetFluxData()
116 | {
117 | list($ret, $err) = $this->cdnManager->getFluxData(
118 | array($this->customDomain2),
119 | $this->testStartDate,
120 | $this->testEndDate,
121 | $this->testGranularity
122 | );
123 | $this->assertNull($err);
124 | $this->assertNotNull($ret);
125 | }
126 |
127 | public function testGetCdnLogList()
128 | {
129 | $domain = getenv('QINIU_TEST_DOMAIN');
130 | list($ret, $err) = $this->cdnManager->getCdnLogList(array($domain), $this->testLogDate);
131 | $this->assertNull($err);
132 | $this->assertNotNull($ret);
133 | }
134 |
135 | public function testCreateTimestampAntiLeechUrl()
136 | {
137 | $signUrl = $this->cdnManager->createTimestampAntiLeechUrl($this->refreshUrl, $this->encryptKey, 3600);
138 | $response = Client::get($signUrl);
139 | $this->assertNull($response->error);
140 | $this->assertEquals($response->statusCode, 200);
141 |
142 | $signUrl = $this->cdnManager->createTimestampAntiLeechUrl(
143 | $this->refreshUrl . '?qiniu',
144 | $this->encryptKey,
145 | 3600
146 | );
147 | $response = Client::get($signUrl);
148 | $this->assertNull($response->error);
149 | $this->assertEquals($response->statusCode, 200);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/Qiniu/Storage/FormUploader.php:
--------------------------------------------------------------------------------
1 | "",
29 | * "key" => ""
30 | * ]
31 | */
32 | public static function put(
33 | $upToken,
34 | $key,
35 | $data,
36 | $config,
37 | $params,
38 | $mime,
39 | $fname,
40 | $reqOpt = null
41 | ) {
42 | if ($reqOpt == null) {
43 | $reqOpt = new RequestOptions();
44 | }
45 | $fields = array('token' => $upToken);
46 | if ($key === null) {
47 | } else {
48 | $fields['key'] = $key;
49 | }
50 |
51 | //enable crc32 check by default
52 | $fields['crc32'] = \Qiniu\crc32_data($data);
53 |
54 | if ($params) {
55 | foreach ($params as $k => $v) {
56 | $fields[$k] = $v;
57 | }
58 | }
59 |
60 | list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($upToken);
61 | if ($err != null) {
62 | return array(null, $err);
63 | }
64 |
65 | list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt);
66 | if ($err != null) {
67 | return array(null, $err);
68 | }
69 |
70 |
71 | $response = Client::multipartPost(
72 | $upHost,
73 | $fields,
74 | 'file',
75 | $fname,
76 | $data,
77 | $mime,
78 | array(),
79 | $reqOpt
80 | );
81 | if (!$response->ok()) {
82 | return array(null, new Error($upHost, $response));
83 | }
84 | return array($response->json(), null);
85 | }
86 |
87 | /**
88 | * 上传文件到七牛,内部使用
89 | *
90 | * @param string $upToken 上传凭证
91 | * @param string $key 上传文件名
92 | * @param string $filePath 上传文件的路径
93 | * @param Config $config 上传配置
94 | * @param string $params 自定义变量,规格参考
95 | * https://developer.qiniu.com/kodo/manual/1235/vars#xvar
96 | * @param string $mime 上传数据的mimeType
97 | *
98 | * @return array 包含已上传文件的信息,类似:
99 | * [
100 | * "hash" => "",
101 | * "key" => ""
102 | * ]
103 | */
104 | public static function putFile(
105 | $upToken,
106 | $key,
107 | $filePath,
108 | $config,
109 | $params,
110 | $mime,
111 | $reqOpt = null
112 | ) {
113 | if ($reqOpt == null) {
114 | $reqOpt = new RequestOptions();
115 | }
116 |
117 | $fields = array('token' => $upToken, 'file' => self::createFile($filePath, $mime));
118 | if ($key !== null) {
119 | $fields['key'] = $key;
120 | }
121 |
122 | $fields['crc32'] = \Qiniu\crc32_file($filePath);
123 |
124 | if ($params) {
125 | foreach ($params as $k => $v) {
126 | $fields[$k] = $v;
127 | }
128 | }
129 | $fields['key'] = $key;
130 | $headers = array('Content-Type' => 'multipart/form-data');
131 |
132 | list($accessKey, $bucket, $err) = \Qiniu\explodeUpToken($upToken);
133 | if ($err != null) {
134 | return array(null, $err);
135 | }
136 |
137 | list($upHost, $err) = $config->getUpHostV2($accessKey, $bucket, $reqOpt);
138 | if ($err != null) {
139 | return array(null, $err);
140 | }
141 |
142 | $response = Client::post($upHost, $fields, $headers, $reqOpt);
143 | if (!$response->ok()) {
144 | return array(null, new Error($upHost, $response));
145 | }
146 | return array($response->json(), null);
147 | }
148 |
149 | private static function createFile($filename, $mime)
150 | {
151 | // PHP 5.5 introduced a CurlFile object that deprecates the old @filename syntax
152 | // See: https://wiki.php.net/rfc/curl-file-upload
153 | if (function_exists('curl_file_create')) {
154 | return curl_file_create($filename, $mime);
155 | }
156 |
157 | // Use the old style if using an older version of PHP
158 | $value = "@{$filename}";
159 | if (!empty($mime)) {
160 | $value .= ';type=' . $mime;
161 | }
162 |
163 | return $value;
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/src/Qiniu/Storage/UploadManager.php:
--------------------------------------------------------------------------------
1 | config = $config;
33 |
34 | if ($reqOpt === null) {
35 | $reqOpt = new RequestOptions();
36 | }
37 |
38 | $this->reqOpt = $reqOpt;
39 | }
40 |
41 | /**
42 | * 上传二进制流到七牛
43 | *
44 | * @param string $upToken 上传凭证
45 | * @param string $key 上传文件名
46 | * @param string $data 上传二进制流
47 | * @param array $params 自定义变量,规格参考
48 | * http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
49 | * @param string $mime 上传数据的mimeType
50 | * @param string $fname
51 | * @param RequestOptions $reqOpt
52 | * @return array 包含已上传文件的信息,类似:
53 | * [
54 | * "hash" => "",
55 | * "key" => ""
56 | * ]
57 | */
58 | public function put(
59 | $upToken,
60 | $key,
61 | $data,
62 | $params = null,
63 | $mime = 'application/octet-stream',
64 | $fname = "default_filename",
65 | $reqOpt = null
66 | ) {
67 | $reqOpt = $reqOpt === null ? $this->reqOpt : $reqOpt;
68 |
69 | $params = self::trimParams($params);
70 | return FormUploader::put(
71 | $upToken,
72 | $key,
73 | $data,
74 | $this->config,
75 | $params,
76 | $mime,
77 | $fname,
78 | $reqOpt
79 | );
80 | }
81 |
82 |
83 | /**
84 | * 上传文件到七牛
85 | *
86 | * @param string $upToken 上传凭证
87 | * @param string $key 上传文件名
88 | * @param string $filePath 上传文件的路径
89 | * @param array $params 定义变量,规格参考
90 | * http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
91 | * @param boolean $mime 上传数据的mimeType
92 | * @param string $checkCrc 是否校验crc32
93 | * @param string $resumeRecordFile 断点续传文件路径 默认为null
94 | * @param string $version 分片上传版本 目前支持v1/v2版本 默认v1
95 | * @param int $partSize 分片上传v2字段 默认大小为4MB 分片大小范围为1 MB - 1 GB
96 | *
97 | * @return array 包含已上传文件的信息,类似:
98 | * [
99 | * "hash" => "",
100 | * "key" => ""
101 | * ]
102 | * @throws \Exception
103 | */
104 | public function putFile(
105 | $upToken,
106 | $key,
107 | $filePath,
108 | $params = null,
109 | $mime = 'application/octet-stream',
110 | $checkCrc = false,
111 | $resumeRecordFile = null,
112 | $version = 'v1',
113 | $partSize = config::BLOCK_SIZE,
114 | $reqOpt = null
115 | ) {
116 | $reqOpt = $reqOpt === null ? $this->reqOpt : $reqOpt;
117 |
118 | $file = fopen($filePath, 'rb');
119 | if ($file === false) {
120 | throw new \Exception("file can not open", 1);
121 | }
122 | $params = self::trimParams($params);
123 | $stat = fstat($file);
124 | $size = $stat['size'];
125 | if ($size <= Config::BLOCK_SIZE) {
126 | $data = fread($file, $size);
127 | fclose($file);
128 | if ($data === false) {
129 | throw new \Exception("file can not read", 1);
130 | }
131 | return FormUploader::put(
132 | $upToken,
133 | $key,
134 | $data,
135 | $this->config,
136 | $params,
137 | $mime,
138 | basename($filePath),
139 | $reqOpt
140 | );
141 | }
142 |
143 | $up = new ResumeUploader(
144 | $upToken,
145 | $key,
146 | $file,
147 | $size,
148 | $params,
149 | $mime,
150 | $this->config,
151 | $resumeRecordFile,
152 | $version,
153 | $partSize,
154 | $reqOpt
155 | );
156 | $ret = $up->upload(basename($filePath));
157 | fclose($file);
158 | return $ret;
159 | }
160 |
161 | public static function trimParams($params)
162 | {
163 | if ($params === null) {
164 | return null;
165 | }
166 | $ret = array();
167 | foreach ($params as $k => $v) {
168 | $pos1 = strpos($k, 'x:');
169 | $pos2 = strpos($k, 'x-qn-meta-');
170 | if (($pos1 === 0 || $pos2 === 0) && !empty($v)) {
171 | $ret[$k] = $v;
172 | }
173 | }
174 | return $ret;
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/HeaderTest.php:
--------------------------------------------------------------------------------
1 | array('200'),
12 | ':x-test-1' => array('hello1'),
13 | ':x-Test-2' => array('hello2'),
14 | 'content-type' => array('application/json'),
15 | 'CONTENT-LENGTH' => array(1234),
16 | 'oRiGin' => array('https://www.qiniu.com'),
17 | 'ReFer' => array('www.qiniu.com'),
18 | 'Last-Modified' => array('Mon, 06 Sep 2021 06:44:52 GMT'),
19 | 'acCePt-ChArsEt' => array('utf-8'),
20 | 'x-test-3' => array('hello3'),
21 | 'cache-control' => array('no-cache', 'no-store'),
22 | );
23 |
24 | public function testNormalizeKey()
25 | {
26 | $except = array(
27 | ':status',
28 | ':x-test-1',
29 | ':x-Test-2',
30 | 'Content-Type',
31 | 'Content-Length',
32 | 'Origin',
33 | 'Refer',
34 | 'Last-Modified',
35 | 'Accept-Charset',
36 | 'X-Test-3',
37 | 'Cache-Control'
38 | );
39 | $actual = array_map(function ($str) {
40 | return Header::normalizeKey($str);
41 | }, array_keys($this->heads));
42 | $this->assertEquals($actual, $except);
43 | }
44 |
45 |
46 | public function testInvalidKeyName()
47 | {
48 | $except = array(
49 | 'a:x-test-1',
50 | );
51 |
52 | $actual = array_map(function ($str) {
53 | return Header::normalizeKey($str);
54 | }, $except);
55 |
56 | $this->assertEquals($except, $actual);
57 | }
58 |
59 | public function testGetRawData()
60 | {
61 | $header = new Header($this->heads);
62 | foreach ($this->heads as $k => $v) {
63 | $rawHeader = $header->getRawData();
64 | $this->assertEquals($v, $rawHeader[Header::normalizeKey($k)]);
65 | }
66 | }
67 |
68 | public function testOffsetExists()
69 | {
70 | $header = new Header($this->heads);
71 | foreach (array_keys($this->heads) as $k) {
72 | $this->assertNotNull($header[$k]);
73 | }
74 |
75 | $except = array(
76 | ':status',
77 | ':x-test-1',
78 | ':x-Test-2',
79 | 'Content-Type',
80 | 'Content-Length',
81 | 'Origin',
82 | 'Refer',
83 | 'Last-Modified',
84 | 'Accept-Charset',
85 | 'X-Test-3',
86 | 'Cache-Control'
87 | );
88 | foreach ($except as $k) {
89 | $this->assertNotNull($header[$k], $k." is null");
90 | }
91 | }
92 |
93 | public function testOffsetGet()
94 | {
95 | $header = new Header($this->heads);
96 | foreach ($this->heads as $k => $v) {
97 | $this->assertEquals($v[0], $header[$k]);
98 | }
99 |
100 | $this->assertNull($header['no-exist']);
101 | }
102 |
103 | public function testOffsetSet()
104 | {
105 | $header = new Header($this->heads);
106 | $header["X-Test-3"] = "hello";
107 | $this->assertEquals("hello", $header["X-Test-3"]);
108 | $header["x-test-3"] = "hello test3";
109 | $this->assertEquals("hello test3", $header["x-test-3"]);
110 | $header[":x-Test-2"] = "hello";
111 | $this->assertEquals("hello", $header[":x-Test-2"]);
112 | $header[":x-test-2"] = "hello test2";
113 | $this->assertEquals("hello", $header[":x-Test-2"]);
114 | }
115 |
116 | public function testOffsetUnset()
117 | {
118 | $header = new Header($this->heads);
119 | unset($header["X-Test-3"]);
120 | $this->assertFalse(isset($header["X-Test-3"]));
121 |
122 | $header = new Header($this->heads);
123 | unset($header["x-test-3"]);
124 | $this->assertFalse(isset($header["x-test-3"]));
125 |
126 | $header = new Header($this->heads);
127 | unset($header[":x-test-2"]);
128 | $this->assertTrue(isset($header[":x-Test-2"]));
129 |
130 | $header = new Header($this->heads);
131 | unset($header[":x-Test-2"]);
132 | $this->assertFalse(isset($header[":x-Test-2"]));
133 | }
134 |
135 | public function testGetIterator()
136 | {
137 | $header = new Header($this->heads);
138 |
139 | $hasException = false;
140 | try {
141 | foreach ($header as $k => $v) {
142 | $hasException = !isset($header[$k]);
143 | }
144 | } catch (\Exception $e) {
145 | $hasException = true;
146 | }
147 | $this->assertFalse($hasException);
148 | }
149 |
150 | public function testEmptyHeaderIterator()
151 | {
152 | $emptyHeader = new Header();
153 |
154 | $hasException = false;
155 | try {
156 | foreach ($emptyHeader as $k => $v) {
157 | $hasException = !isset($header[$k]);
158 | }
159 | } catch (\Exception $e) {
160 | $hasException = true;
161 | }
162 | $this->assertFalse($hasException);
163 | }
164 |
165 | public function testCount()
166 | {
167 | $header = new Header($this->heads);
168 |
169 | $this->assertEquals(count($this->heads), count($header));
170 | }
171 |
172 | public function testFromRaw()
173 | {
174 | $lines = array();
175 | foreach ($this->heads as $k => $vs) {
176 | foreach ($vs as $v) {
177 | array_push($lines, $k . ": " . $v);
178 | }
179 | }
180 | $raw = implode("\r\n", $lines);
181 | $headerFromRaw = Header::fromRawText($raw);
182 | $this->assertEquals(new Header($this->heads), $headerFromRaw);
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/HttpTest.php:
--------------------------------------------------------------------------------
1 | assertEquals(200, $response->statusCode);
16 | $this->assertNotNull($response->body);
17 | $this->assertNull($response->error);
18 | }
19 |
20 | public function testGetQiniu()
21 | {
22 | $response = Client::get('upload.qiniu.com');
23 | $this->assertEquals(405, $response->statusCode);
24 | $this->assertNotNull($response->body);
25 | $this->assertNotNull($response->xReqId());
26 | $this->assertNotNull($response->xLog());
27 | $this->assertNotNull($response->error);
28 | }
29 |
30 | public function testGetTimeout()
31 | {
32 | $reqOpt = new RequestOptions();
33 | $reqOpt->timeout = 1;
34 | $response = Client::get('localhost:9000/timeout.php', array(), $reqOpt);
35 | $this->assertEquals(-1, $response->statusCode);
36 | }
37 |
38 | public function testGetRedirect()
39 | {
40 | $response = Client::get('localhost:9000/redirect.php');
41 | $this->assertEquals(200, $response->statusCode);
42 | $this->assertEquals('application/json;charset=UTF-8', $response->normalizedHeaders['Content-Type']);
43 | $respData = $response->json();
44 | $this->assertEquals('ok', $respData['msg']);
45 | }
46 |
47 | public function testDelete()
48 | {
49 | $response = Client::delete('uc.qbox.me/bucketTagging', array());
50 | $this->assertEquals(401, $response->statusCode);
51 | $this->assertNotNull($response->body);
52 | $this->assertNotNull($response->error);
53 | }
54 |
55 | public function testDeleteQiniu()
56 | {
57 | $response = Client::delete('uc.qbox.me/bucketTagging', array());
58 | $this->assertEquals(401, $response->statusCode);
59 | $this->assertNotNull($response->body);
60 | $this->assertNotNull($response->xReqId());
61 | $this->assertNotNull($response->xLog());
62 | $this->assertNotNull($response->error);
63 | }
64 |
65 | public function testDeleteTimeout()
66 | {
67 | $reqOpt = new RequestOptions();
68 | $reqOpt->timeout = 1;
69 | $response = Client::delete('localhost:9000/timeout.php', array(), $reqOpt);
70 | $this->assertEquals(-1, $response->statusCode);
71 | }
72 |
73 |
74 | public function testPost()
75 | {
76 | $response = Client::post('qiniu.com', null);
77 | $this->assertEquals(200, $response->statusCode);
78 | $this->assertNotNull($response->body);
79 | $this->assertNull($response->error);
80 | }
81 |
82 | public function testPostQiniu()
83 | {
84 | $response = Client::post('upload.qiniu.com', null);
85 | $this->assertEquals(400, $response->statusCode);
86 | $this->assertNotNull($response->body);
87 | $this->assertNotNull($response->xReqId());
88 | $this->assertNotNull($response->xLog());
89 | $this->assertNotNull($response->error);
90 | }
91 |
92 | public function testPostTimeout()
93 | {
94 | $reqOpt = new RequestOptions();
95 | $reqOpt->timeout = 1;
96 | $response = Client::post('localhost:9000/timeout.php', null, array(), $reqOpt);
97 | $this->assertEquals(-1, $response->statusCode);
98 | }
99 |
100 | public function testSocks5Proxy()
101 | {
102 | $reqOpt = new RequestOptions();
103 | $reqOpt->proxy = 'socks5://localhost:8080';
104 | $response = Client::post('qiniu.com', null, array(), $reqOpt);
105 | $this->assertEquals(-1, $response->statusCode);
106 |
107 | $reqOpt->proxy_user_password = 'user:pass';
108 | $response = Client::post('qiniu.com', null, array(), $reqOpt);
109 | $this->assertEquals(200, $response->statusCode);
110 | }
111 |
112 | public function testPut()
113 | {
114 | $response = Client::PUT('uc.qbox.me/bucketTagging', null);
115 | $this->assertEquals(401, $response->statusCode);
116 | $this->assertNotNull($response->body);
117 | $this->assertNotNull($response->error);
118 | }
119 |
120 | public function testPutQiniu()
121 | {
122 | $response = Client::put('uc.qbox.me/bucketTagging', null);
123 | $this->assertEquals(401, $response->statusCode);
124 | $this->assertNotNull($response->body);
125 | $this->assertNotNull($response->xReqId());
126 | $this->assertNotNull($response->xLog());
127 | $this->assertNotNull($response->error);
128 | }
129 |
130 |
131 | public function testPutTimeout()
132 | {
133 | $reqOpt = new RequestOptions();
134 | $reqOpt->timeout = 1;
135 | $response = Client::put('localhost:9000/timeout.php', null, array(), $reqOpt);
136 | $this->assertEquals(-1, $response->statusCode);
137 | }
138 |
139 | public function testNeedRetry()
140 | {
141 | $testCases = array_merge(
142 | array(array(-1, true)),
143 | array_map(function ($i) {
144 | return array($i, false);
145 | }, range(100, 499)),
146 | array_map(function ($i) {
147 | if (in_array($i, array(
148 | 501, 509, 573, 579, 608, 612, 614, 616, 618, 630, 631, 632, 640, 701
149 | ))) {
150 | return array($i, false);
151 | }
152 | return array($i, true);
153 | }, range(500, 799))
154 | );
155 | $resp = new Response(-1, 222, array(), '{"msg": "mock"}', null);
156 | foreach ($testCases as $testCase) {
157 | list($code, $expectNeedRetry) = $testCase;
158 | $resp->statusCode = $code;
159 | $msg = $resp->statusCode . ' need' . ($expectNeedRetry ? '' : ' NOT') . ' retry';
160 | $this->assertEquals($expectNeedRetry, $resp->needRetry(), $msg);
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/tests/Qiniu/Tests/FormUpTest.php:
--------------------------------------------------------------------------------
1 | batch($ops);
43 | }
44 |
45 | private static function getObjectKey($key)
46 | {
47 | $result = $key . rand();
48 | self::$keysToCleanup[] = $result;
49 | return $result;
50 | }
51 |
52 | public function testData()
53 | {
54 | $key = self::getObjectKey('formput');
55 | $token = self::$auth->uploadToken(self::$bucketName);
56 | list($ret, $error) = FormUploader::put($token, $key, 'hello world', self::$cfg, null, 'text/plain', null);
57 | $this->assertNull($error);
58 | $this->assertNotNull($ret['hash']);
59 | }
60 |
61 | public function testDataWithProxy()
62 | {
63 | $key = self::getObjectKey('formput');
64 | $token = self::$auth->uploadToken(self::$bucketName);
65 | list($ret, $error) = FormUploader::put(
66 | $token,
67 | $key,
68 | 'hello world',
69 | self::$cfg,
70 | null,
71 | 'text/plain',
72 | null,
73 | $this->makeReqOpt()
74 | );
75 | $this->assertNull($error);
76 | $this->assertNotNull($ret['hash']);
77 | }
78 |
79 | public function testData2()
80 | {
81 | $key = self::getObjectKey('formput');
82 | $upManager = new UploadManager();
83 | $token = self::$auth->uploadToken(self::$bucketName);
84 | list($ret, $error) = $upManager->put($token, $key, 'hello world', null, 'text/plain', null);
85 | $this->assertNull($error);
86 | $this->assertNotNull($ret['hash']);
87 | }
88 |
89 | public function testData2WithProxy()
90 | {
91 | $key = self::getObjectKey('formput');
92 | $upManager = new UploadManager();
93 | $token = self::$auth->uploadToken(self::$bucketName);
94 | list($ret, $error) = $upManager->put(
95 | $token,
96 | $key,
97 | 'hello world',
98 | null,
99 | 'text/plain',
100 | null,
101 | $this->makeReqOpt()
102 | );
103 | $this->assertNull($error);
104 | $this->assertNotNull($ret['hash']);
105 | }
106 |
107 | public function testDataFailed()
108 | {
109 | $key = self::getObjectKey('formput');
110 | $token = self::$auth->uploadToken('fakebucket');
111 | list($ret, $error) = FormUploader::put(
112 | $token,
113 | $key,
114 | 'hello world',
115 | self::$cfg,
116 | null,
117 | 'text/plain',
118 | null
119 | );
120 | $this->assertNull($ret);
121 | $this->assertNotNull($error);
122 | }
123 |
124 | public function testFile()
125 | {
126 | $key = self::getObjectKey('formPutFile');
127 | $token = self::$auth->uploadToken(self::$bucketName, $key);
128 | list($ret, $error) = FormUploader::putFile(
129 | $token,
130 | $key,
131 | __file__,
132 | self::$cfg,
133 | null,
134 | 'text/plain',
135 | null
136 | );
137 | $this->assertNull($error);
138 | $this->assertNotNull($ret['hash']);
139 | }
140 |
141 | public function testFileWithProxy()
142 | {
143 | $key = self::getObjectKey('formPutFile');
144 | $token = self::$auth->uploadToken(self::$bucketName, $key);
145 | list($ret, $error) = FormUploader::putFile(
146 | $token,
147 | $key,
148 | __file__,
149 | self::$cfg,
150 | null,
151 | 'text/plain',
152 | $this->makeReqOpt()
153 | );
154 | $this->assertNull($error);
155 | $this->assertNotNull($ret['hash']);
156 | }
157 |
158 | public function testFile2()
159 | {
160 | $key = self::getObjectKey('formPutFile');
161 | $token = self::$auth->uploadToken(self::$bucketName, $key);
162 | $upManager = new UploadManager();
163 | list($ret, $error) = $upManager->putFile($token, $key, __file__, null, 'text/plain', null);
164 | $this->assertNull($error);
165 | $this->assertNotNull($ret['hash']);
166 | }
167 |
168 | public function testFile2WithProxy()
169 | {
170 | $key = self::getObjectKey('formPutFile');
171 | $token = self::$auth->uploadToken(self::$bucketName, $key);
172 | $upManager = new UploadManager();
173 | list($ret, $error) = $upManager->putFile(
174 | $token,
175 | $key,
176 | __file__,
177 | null,
178 | 'text/plain',
179 | false,
180 | null,
181 | 'v1',
182 | Config::BLOCK_SIZE,
183 | $this->makeReqOpt()
184 | );
185 | $this->assertNull($error);
186 | $this->assertNotNull($ret['hash']);
187 | }
188 |
189 | public function testFileFailed()
190 | {
191 | $key = self::getObjectKey('fakekey');
192 | $token = self::$auth->uploadToken('fakebucket', $key);
193 | list($ret, $error) = FormUploader::putFile($token, $key, __file__, self::$cfg, null, 'text/plain', null);
194 | $this->assertNull($ret);
195 | $this->assertNotNull($error);
196 | }
197 |
198 | private function makeReqOpt()
199 | {
200 | $reqOpt = new RequestOptions();
201 | $reqOpt->proxy = 'socks5://127.0.0.1:8080';
202 | $reqOpt->proxy_user_password = 'user:pass';
203 | return $reqOpt;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/src/Qiniu/Http/Client.php:
--------------------------------------------------------------------------------
1 | $val) {
85 | array_push($data, '--' . $mimeBoundary);
86 | array_push($data, "Content-Disposition: form-data; name=\"$key\"");
87 | array_push($data, '');
88 | array_push($data, $val);
89 | }
90 |
91 | array_push($data, '--' . $mimeBoundary);
92 | $finalMimeType = empty($mimeType) ? 'application/octet-stream' : $mimeType;
93 | $finalFileName = self::escapeQuotes($fileName);
94 | array_push($data, "Content-Disposition: form-data; name=\"$name\"; filename=\"$finalFileName\"");
95 | array_push($data, "Content-Type: $finalMimeType");
96 | array_push($data, '');
97 | array_push($data, $fileBody);
98 |
99 | array_push($data, '--' . $mimeBoundary . '--');
100 | array_push($data, '');
101 |
102 | $body = implode("\r\n", $data);
103 | $contentType = 'multipart/form-data; boundary=' . $mimeBoundary;
104 | $headers['Content-Type'] = $contentType;
105 | $request = new Request('POST', $url, $headers, $body, $opt);
106 | return self::sendRequest($request);
107 | }
108 |
109 | private static function userAgent()
110 | {
111 | $sdkInfo = "QiniuPHP/" . Config::SDK_VER;
112 |
113 | $systemInfo = php_uname("s");
114 | $machineInfo = php_uname("m");
115 |
116 | $envInfo = "($systemInfo/$machineInfo)";
117 |
118 | $phpVer = phpversion();
119 |
120 | $ua = "$sdkInfo $envInfo PHP/$phpVer";
121 | return $ua;
122 | }
123 |
124 | /**
125 | * @param Request $request
126 | * @return Response
127 | */
128 | public static function sendRequestWithMiddleware($request)
129 | {
130 | $middlewares = $request->opt->middlewares;
131 | $handle = Middleware\compose($middlewares, function ($req) {
132 | return Client::sendRequest($req);
133 | });
134 | return $handle($request);
135 | }
136 |
137 | /**
138 | * @param Request $request
139 | * @return Response
140 | */
141 | public static function sendRequest($request)
142 | {
143 | $t1 = microtime(true);
144 | $ch = curl_init();
145 | $options = array(
146 | CURLOPT_USERAGENT => self::userAgent(),
147 | CURLOPT_RETURNTRANSFER => true,
148 | CURLOPT_HEADER => true,
149 | CURLOPT_NOBODY => false,
150 | CURLOPT_CUSTOMREQUEST => $request->method,
151 | CURLOPT_URL => $request->url,
152 | );
153 | foreach ($request->opt->getCurlOpt() as $k => $v) {
154 | $options[$k] = $v;
155 | }
156 | // Handle open_basedir & safe mode
157 | if (!ini_get('safe_mode') && !ini_get('open_basedir')) {
158 | $options[CURLOPT_FOLLOWLOCATION] = true;
159 | }
160 | if (!empty($request->headers)) {
161 | $headers = array();
162 | foreach ($request->headers as $key => $val) {
163 | array_push($headers, "$key: $val");
164 | }
165 | $options[CURLOPT_HTTPHEADER] = $headers;
166 | }
167 | curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
168 | if (!empty($request->body)) {
169 | $options[CURLOPT_POSTFIELDS] = $request->body;
170 | }
171 | curl_setopt_array($ch, $options);
172 | $result = curl_exec($ch);
173 | $t2 = microtime(true);
174 | $duration = round($t2 - $t1, 3);
175 | $ret = curl_errno($ch);
176 | if ($ret !== 0) {
177 | $r = new Response(-1, $duration, array(), null, curl_error($ch));
178 | curl_close($ch);
179 | return $r;
180 | }
181 | $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
182 | $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
183 | $headers = Header::parseRawText(substr($result, 0, $header_size));
184 | $body = substr($result, $header_size);
185 | curl_close($ch);
186 | return new Response($code, $duration, $headers, $body, null);
187 | }
188 |
189 | private static function escapeQuotes($str)
190 | {
191 | if (is_null($str)) {
192 | return null;
193 | }
194 | $find = array("\\", "\"");
195 | $replace = array("\\\\", "\\\"");
196 | return str_replace($find, $replace, $str);
197 | }
198 | }
199 |
--------------------------------------------------------------------------------