我正在后端使用 PHP 创建一个在线代码编辑器,用户可以在其中创建可以包含图像的代码项目。我在google上创建了一个服务帐户并获得了私钥。我想使用 PHP 将照片上传到 Google 云存储 API,使用 cURL 将图像存储在云上并检索它们。 但是..
我听说过 google API PHP 客户端库,但它使用 Composer,而我的 Web 主机不允许 Composer 或 shell 访问,而且该库太大,我的 Web 主机的存储容量非常有限(这就是为什么我首先考虑谷歌云存储来存储上传的照片)。
我了解访问令牌,并且能够使用访问令牌使用 PHP 成功将图像上传到存储,但这些令牌是临时的,只能持续一个小时,即使刷新令牌也是临时的。 所以.. 我想要一种永久的方式来使用“本机 PHP”调用 api 并上传到谷歌云。我创建了一个服务帐户并获取了私钥,但无法成功上传到 API。到目前为止,这是我的代码:
// I previously initialized the variables $bucketName , $projectId , and $jsonKey
function is_valid_image($file) {
$allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'];
if (!in_array($file['type'], $allowed_types)) {
return false;
}
return true;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_FILES['image'])) {
if (is_valid_image($_FILES['image'])) {
$localFilePath = $_FILES['image']['tmp_name'];
$objectName = $_FILES['image']['name'];
$fileContent = base64_encode(file_get_contents($localFilePath));
$uploadUrl = "https://storage.googleapis.com/upload/storage/v1/b/{$bucketName}/o?uploadType=media&name={$objectName}";
$serviceAccountKey = json_decode($jsonKey);
$authHeader = "Authorization: Bearer " . $serviceAccountKey['private_key'];
$ch = curl_init($uploadUrl);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['name' => $objectName, 'content' => $fileContent]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
$authHeader,
]);
$response = curl_exec($ch);
echo $response;
curl_close($ch);
require "db_update.php";
} else {
echo 'Invalid file type. Please upload a valid image (JPEG, JPG, PNG, GIF).';
}
} else {
echo 'Error uploading picture. Please try again.';
}
但它不起作用,我收到了这样的回复:
{ "error": { "code": 401, "message": "Invalid Credentials", "errors": [ { "message": "Invalid Credentials", "domain": "global", "reason": "authError", "locationType": "header", "location": "Authorization" } ] } }
我做错了什么?当我使用临时令牌时,它工作得很好,如何在不使用谷歌存储 API 库的情况下正确完成它?
Google Cloud Storage API 需要访问令牌进行身份验证,而不是直接使用私钥(而且一旦您发出私钥,它就不再是真正的私有密钥,我会轮换它)。
此外,对于
uploadType=media
,您的有效负载应该是文件的二进制数据,而不是 JSON 有效负载中的 Base64 编码字符串。