php接入百度网盘实现文件上传下载

授权前准备

官方文档地址:https://pan.baidu.com/union/doc/ol0rsap9s 

在授权之前,您需要先完成创建自己的应用。具体流程参见使用入门章节。

主要包括以下流程:

1.进入百度网盘开放平台,点击右上角 “申请接入”。

2.登录您的百度帐号。

3.完成开发者认证,我们提供了两种认证类型供您选择:个人认证、企业认证。

4.前往控制台创建自己的应用,生成AppID、AppKey、SecretKey、SignKey等信息。

目前个人认证下可最多创建 2 个应用,企业认证下可最多创建 10 个应用。
可创建两种类型的应用:硬件应用和软件应用。

5.至此,完成应用的创建。

授权码模式

我使用的是授权码模式:他的大致流程就是先要获得一个code,然后通过code获取到我们最终要使用的access_token。

        获取code

        将其中的参数替换成你自己的参数,回调地址如果是开发环境可以先传oob

http://openapi.baidu.com/oauth/2.0/authorize?
response_type=code&
client_id=您应用的AppKey&
redirect_uri=您应用的授权回调地址&
scope=basic,netdisk&
device_id=您应用的AppID

        如果回调地址传的是oob的话会出现授权页面,需要手动复制code

        注意:一个code只能使用一次

        获取access_token

        通过code即可获取到access_token

        接口文档:https://pan.baidu.com/union/doc/al0rwqzzl

                code:第一步获取到的值

                redirect_uri:如果没有回调地址可以填oob

                回调地址还需要在百度网盘管理平台进行配置,并且一个小时之后生效

     回调地址就是百度会根据你提供的回调地址来调取你的接口,会传code给你如果你请求的时候带上state也会一并返回给你,所以必须保证你的接口是可以通过公网访问的

GET https://openapi.baidu.com/oauth/2.0/token?
grant_type=authorization_code&
code=用户授权码 Code 值&
client_id=您应用的AppKey&
client_secret=您应用的SecretKey&
redirect_uri=您应用设置的授权回调地址

示例代码:state是自定义参数,传的话他会在回调的时候给你带着回来

        

    public function getAuth($code,$panId)
    {
        if (empty($code)) {
            exit();
        }
        $config = [
            'client_id' => $this->app_key,
            'SecretKey' => $this->secret_key,
            'redirect_uri' => $this->redirect_url,
            'state'=>$panId
        ];
        $url = 'https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code='.$code.'&client_id=' . $config['client_id'] ."&state=".$config['state']. '&client_secret=' . $config['SecretKey'] . '&redirect_uri=' . $config['redirect_uri'];
        $result = Http::get($url);
        return json_decode($result,true);

    }

        注意:access_token会过期,一般是30天,需要定时刷新

刷新access_token示例代码:

        refreshToken:会在获取access_token成功的时候一并返回给你   

    function refreshToken($refreshToken) {
        // 构建请求 URL 和参数
        $url = 'https://openapi.baidu.com/oauth/2.0/token';
        $params = [
            'grant_type' => 'refresh_token',
            'refresh_token' => $refreshToken,
            'client_id' => Config::get("site.AppKey"),
            'client_secret' => Config::get("site.SecretKey")
        ];
        $query = http_build_query($params);
        $requestUrl = $url . '?' . $query;
        // 发送 HTTP GET 请求
        $response = Http::get($requestUrl);
        return json_decode($response,true);
    }

 文件上传

        百度网盘有两种文件上传的方式,一种是分片上传,可以上传大文件,还有一种是单片上传

,单片上传支持的最大文件为2G。这里介绍的是分片上传,单步上传可以自己看官方文档

  官方文档:https://pan.baidu.com/union/doc/olkuuy5kz

        预上传

        预上传是通知网盘云端新建一个上传任务,网盘云端返回唯一ID uploadid 来标识此上传任务。

        代码示例:

        

function precreate($accessToken, $filePath, $fileSize, $md5s)
    {
        $url = "https://pan.baidu.com/rest/2.0/xpan/file?method=precreate&access_token={$accessToken}";

        $data = [
            'path' => $filePath,
            'size' => $fileSize,
            'isdir' => 0,
            'block_list' => json_encode($md5s),
            'autoinit' => 1,
            'rtype' => 1
        ];

        $options = [
            'http' => [
                'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
                'method' => 'POST',
                'content' => http_build_query($data),
            ],
        ];
        $context = stream_context_create($options);
        $response = file_get_contents($url, false, $context);
        return json_decode($response, true);
    }

      预上传之后会返回上传id,也就是uploadid

响应示例:

        


{
	"path": "/apps/test/test.jpg",
	"uploadid": "N1-NjEuMTM1LjE2OS44NDoxNTQ1ODE4MTY1OjgzNDM1NTUyMzU5MjIxMTMzMDc=",
	"return_type": 1,
	"block_list": [0, 1, 2],
	"errno": 0,
	"request_id": 8343555235922113307
}

分片上传

        分片上传是将大文件按照指定的大小进行切片,然后一片一片的上传。百度网盘推荐按照

4MB进行分片上传

      示例代码:

        

    function uploadSlice($accessToken, $filePath, $uploadId, $partSeq, $chunk,$uploadDomain) {
        $url = $uploadDomain."/rest/2.0/pcs/superfile2?method=upload&access_token={$accessToken}&type=tmpfile&path=" . urlencode($filePath) . "&uploadid={$uploadId}&partseq={$partSeq}";

        // 创建临时文件并写入当前分片内容
        $tempFilePath = tempnam(sys_get_temp_dir(), 'chunk');
        file_put_contents($tempFilePath, $chunk);

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => new CURLFile($tempFilePath)]);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: multipart/form-data']);

        $response = curl_exec($ch);
        if ($response === false) {
            $error = curl_error($ch);
            $errno = curl_errno($ch);
            curl_close($ch);
            unlink($tempFilePath); // 删除临时文件
            return ['errno' => $errno, 'error' => $error];
        }
        curl_close($ch);
        unlink($tempFilePath); // 删除临时文件

        $decodedResponse = json_decode($response, true);
        if ($decodedResponse === null) {
            throw new Exception("upload error");
        }

        return $decodedResponse;
    }

创建文件

        创建文件就是将前面上传的分片进行合并,完成文件上传,也是文件上传的最后一步

         示例代码:

                

function createFile($accessToken, $filePath, $fileSize, $md5s, $uploadId)
    {
        $url = "https://pan.baidu.com/rest/2.0/xpan/file?method=create&access_token={$accessToken}";

        $data = [
            'path' => $filePath,
            'size' => $fileSize,
            'isdir' => 0,
            'block_list' => json_encode($md5s),
            'uploadid' => $uploadId,
            'rtype' => 1
        ];

        $options = [
            'http' => [
                'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
                'method' => 'POST',
                'content' => http_build_query($data),
            ],
        ];
        $context = stream_context_create($options);
        $response = file_get_contents($url, false, $context);
        return json_decode($response, true);
    }

下面这是调用文件上传的示例代码,仅供参考

        

function uploadToBaiduPan($accessToken, $localFilePath, $remoteFilePath)
    {
        $fileHandle = fopen($localFilePath, "rb");
        if (!$fileHandle) {
            return ['errno' => -1, 'error' => 'Failed to open file'];
        }

        // 计算文件大小
        $fileSize = filesize($localFilePath);

        // 计算每个分片的MD5值
        $chunkSize = 4 * 1024 * 1024; // 4MB
        $md5s = [];
        while (!feof($fileHandle)) {
            $chunk = fread($fileHandle, $chunkSize);
            $md5s[] = md5($chunk);
        }
        rewind($fileHandle);

        // 预上传
        $precreateResponse = $this->precreate($accessToken, $remoteFilePath, $fileSize, $md5s);
        if ($precreateResponse['errno'] !== 0) {
            fclose($fileHandle);
            return $precreateResponse;
        }

        $uploadId = $precreateResponse['uploadid'];
        $blockList = $precreateResponse['block_list'];

        //获取上传域名
        $uploadDomain = $this->getUploadDomain($accessToken, $remoteFilePath, $uploadId);

        // 分片上传
        $partSeq = 0;
        foreach ($blockList as $block) {
            $chunk = fread($fileHandle, $chunkSize);
            $sliceResponse = $this->uploadSlice($accessToken, $remoteFilePath, $uploadId, $partSeq, $chunk,$uploadDomain);
            $partSeq++;
        }
        fclose($fileHandle);

        // 创建文件
        $createFileResponse = $this->createFile($accessToken, $remoteFilePath, $fileSize, $md5s, $uploadId);
        return $createFileResponse;
    }

    function getUploadDomain($accessToken, $path, $uploadId) {
        // 基础URL
        $baseUrl = "https://d.pcs.baidu.com/rest/2.0/pcs/file?method=locateupload";

        // 请求参数
        $params = [
            'appid' => 250528,
            'access_token' => $accessToken,
            'path' => urlencode($path),
            'uploadid' => $uploadId,
            'upload_version' => '2.0'
        ];

        // 构建完整的请求URL
        $url = $baseUrl . '&' . http_build_query($params);

        // 初始化CURL
        $ch = curl_init();

        // 设置CURL选项
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        // 执行请求并获取响应
        $response = curl_exec($ch);

        // 检查是否有CURL错误
        if (curl_errno($ch)) {
            throw new Exception('CURL Error: ' . curl_error($ch));
        }

        // 关闭CURL
        curl_close($ch);

        // 尝试解析JSON响应
        $jsonResponse = json_decode($response, true);

        // 检查是否解析成功
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception('JSON Decode Error: ' . json_last_error_msg());
        }

        // error_code
        if ($jsonResponse['error_code'] !== 0) {
            throw new Exception('API Error: ' . $jsonResponse['errmsg']);
        }

        // 检查servers字段是否存在并且是数组
        if (!isset($jsonResponse['servers']) || !is_array($jsonResponse['servers'])) {
            throw new Exception('Invalid response structure: servers field missing or not an array');
        }

        // 返回第一个https协议的域名
        foreach ($jsonResponse['servers'] as $server) {
            if (isset($server['server']) && strpos($server['server'], 'https://') === 0) {
                return $server['server'];
            }
        }

        throw new Exception('No HTTPS server found in the response');
    }

 嗷,忘记了,还有一步获取文件上传的接口

        接口文档:https://pan.baidu.com/union/doc/Mlvw5hfnr

上面的getUploadDomain方法就是获取上传域名的方法

        OK,至此,文件上传已经完成

文件下载

        文件下载也是需要分两步,第一步先根据文件上传成功之后返回的fs_id获得文件的详细信息,这个文件的详细信息中就有包含一个blink,这个就是这个文件的下载地址,然后请求这个文件的下载地址就好啦

        示例代码:

                

function downloadFileFromBaiduPan($accessToken, $fids) {

        $dlink ="";
        $result = $this->queryFileMeta($accessToken, $fids);
        // 第二阶段:查询文件信息,获取文件的下载地址 (dlink)
        if ($result['errno'] === 0) {
            $fileList = $result['fileList'];
            foreach (json_decode($fileList,true) as $file) {
                   $dlink=$file['dlink'];
            }
        } else {
            return $result;
        }

        // 第三阶段:下载文件
        $downloadUrl = $dlink . "&access_token={$accessToken}";
        return $downloadUrl;
    }

获取文件详细信息

        示例代码

        

    function queryFileMeta($accessToken, $fsids) {
        // 构建请求 URL
        $url = "https://pan.baidu.com/rest/2.0/xpan/multimedia?dlink=1&method=filemetas&access_token={$accessToken}&fsids=" . json_encode($fsids);
        // 初始化 CURL
        $response = Http::get($url);
        // 检查响应状态码是否为 200
        if (!empty($response)) {
            // 尝试解析 JSON 响应
            $jsonResponse = json_decode($response,true); // 将 JSON 字符串解析为关联数组
            if ($jsonResponse && isset($jsonResponse['errno']) && $jsonResponse['errno'] === 0) {
                // 返回文件信息列表
                $fileList = json_encode($jsonResponse['list']); // 将列表编码为 JSON 字符串
                return ['errno' => 0, 'fileList' => $fileList];
            } else {
                // 处理错误
                return ['errno' => $jsonResponse['errno'] ?? 1, 'errmsg' => $jsonResponse['errmsg'] ?? 'Unknown error'];
            }
        } else {
            // 处理空响应或其他错误
            return ['errno' => 1, 'errmsg' => 'Empty response or request failed'];
        }
    }

好了,至此就是文件上传下载的全部内容了,goodbye

  • 30
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值