授权前准备
官方文档地址: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