PHP项目与Storj分布式存储集成
Storj是一个去中心化的云存储平台,提供安全、私密的对象存储服务,以下是PHP项目集成Storj的主要方式:

通过Storj Uplink CLI集成
安装Storj Uplink:
# Linux/macOS curl -L https://github.com/storj/storj/releases/latest/download/uplink_linux_amd64.zip -o uplink.zip unzip uplink.zip && sudo mv uplink /usr/local/bin/ # 配置访问权限 uplink setup
PHP调用示例:
<?php
class StorjCLI {
private $accessGrant;
public function __construct($accessGrant) {
$this->accessGrant = $accessGrant;
}
public function uploadFile($localPath, $remotePath) {
$escapedLocal = escapeshellarg($localPath);
$escapedRemote = escapeshellarg($remotePath);
$grant = escapeshellarg($this->accessGrant);
$cmd = "uplink cp --access {$grant} {$escapedLocal} sj://{$escapedRemote} 2>&1";
exec($cmd, $output, $returnCode);
return [
'success' => $returnCode === 0,
'message' => implode("\n", $output)
];
}
public function downloadFile($remotePath, $localPath) {
$escapedRemote = escapeshellarg($remotePath);
$escapedLocal = escapeshellarg($localPath);
$grant = escapeshellarg($this->accessGrant);
$cmd = "uplink cp --access {$grant} sj://{$escapedRemote} {$escapedLocal} 2>&1";
exec($cmd, $output, $returnCode);
return [
'success' => $returnCode === 0,
'message' => implode("\n", $output)
];
}
}
// 使用示例
$storj = new StorjCLI('your-access-grant-here');
$result = $storj->uploadFile('/tmp/backup.sql', 'backups/database/2024-01.sql');
print_r($result);
?>
使用Storj HTTP Gateway (S3兼容)
配置S3客户端:
<?php
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Credentials\Credentials;
class StorjS3Client {
private $client;
private $bucket;
public function __construct($accessKey, $secretKey, $bucket) {
// Storj Gateway端点
$endpoint = 'https://gateway.storjshare.io';
$credentials = new Credentials($accessKey, $secretKey);
$this->client = new S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => $endpoint,
'credentials' => $credentials,
'use_path_style_endpoint' => true,
'http' => [
'verify' => true // 生产环境建议开启SSL验证
]
]);
$this->bucket = $bucket;
}
public function uploadFile($localPath, $key) {
try {
$result = $this->client->putObject([
'Bucket' => $this->bucket,
'Key' => $key,
'SourceFile' => $localPath,
'ACL' => 'private'
]);
return [
'success' => true,
'etag' => $result['ETag'],
'url' => $result['ObjectURL']
];
} catch (Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
public function generatePresignedUrl($key, $expiration = '+1 hour') {
$cmd = $this->client->getCommand('GetObject', [
'Bucket' => $this->bucket,
'Key' => $key
]);
$request = $this->client->createPresignedRequest($cmd, $expiration);
return (string) $request->getUri();
}
public function listFiles($prefix = '') {
try {
$objects = $this->client->listObjects([
'Bucket' => $this->bucket,
'Prefix' => $prefix
]);
$files = [];
foreach ($objects['Contents'] as $object) {
$files[] = [
'key' => $object['Key'],
'size' => $object['Size'],
'lastModified' => $object['LastModified']->format('Y-m-d H:i:s')
];
}
return $files;
} catch (Exception $e) {
return [];
}
}
public function deleteFile($key) {
try {
$this->client->deleteObject([
'Bucket' => $this->bucket,
'Key' => $key
]);
return ['success' => true];
} catch (Exception $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
}
// 使用示例
$storj = new StorjS3Client(
'your-access-key',
'your-secret-key',
'your-bucket-name'
);
// 上传文件
$result = $storj->uploadFile('/path/to/file.pdf', 'documents/file.pdf');
// 生成临时访问链接
$url = $storj->generatePresignedUrl('documents/file.pdf', '+2 hours');
echo "Download URL: " . $url;
?>
使用libuplink的PHP扩展
安装PHP扩展(需要CGo交叉编译):
# 编译libuplink for PHP git clone https://github.com/storj-thirdparty/php-uplink.git cd php-uplink phpize ./configure make sudo make install # 配置php.ini echo "extension=uplink.so" >> /etc/php/8.1/cli/php.ini
PHP原生调用:
<?php
// 需要安装uplink PHP扩展
class StorjNative {
private $project;
public function __construct($accessGrant) {
// 初始化Storj项目
$this->project = uplink_project_open_advanced(
uplink_parse_access($accessGrant),
null // 可以指定配置
);
}
public function uploadFile($localPath, $remotePath) {
$file = fopen($localPath, 'rb');
// 创建上传对象
$upload = uplink_upload_object(
$this->project,
'my-bucket',
$remotePath,
null // 可添加上传选项
);
// 分块上传
$buffer = '';
while (!feof($file)) {
$buffer = fread($file, 1024 * 1024); // 1MB chunk
uplink_upload_write($upload, $buffer);
}
uplink_upload_commit($upload);
fclose($file);
return true;
}
public function downloadFile($remotePath, $localPath) {
// 下载对象
$download = uplink_download_object(
$this->project,
'my-bucket',
$remotePath,
null
);
$file = fopen($localPath, 'wb');
$buffer = uplink_download_read($download, 1024 * 1024);
fwrite($file, $buffer);
uplink_download_close($download);
fclose($file);
return true;
}
}
完整项目集成方案
目录结构:
storj-integration/
├── src/
│ ├── StorjClient.php
│ ├── StorjS3Compatible.php
│ └── StorjCLIWrapper.php
├── config/
│ └── storj.php
├── tests/
│ └── StorjTest.php
├── storage/
│ └── adapter.php
└── composer.json
StorjClient.php:
<?php
namespace App\Storage;
class StorjClient {
private $driver;
private $config;
public function __construct(array $config) {
$this->config = $config;
$this->driver = $this->initializeDriver();
}
private function initializeDriver() {
switch ($this->config['driver']) {
case 'cli':
return new StorjCLIWrapper($this->config['access_grant']);
case 's3':
return new StorjS3Compatible(
$this->config['access_key'],
$this->config['secret_key'],
$this->config['bucket']
);
default:
throw new \InvalidArgumentException("Unsupported driver: {$this->config['driver']}");
}
}
public function store($identifier, $content) {
$tempFile = tempnam(sys_get_temp_dir(), 'storj_');
file_put_contents($tempFile, $content);
try {
$result = $this->driver->uploadFile($tempFile, $identifier);
unlink($tempFile);
return $result;
} catch (\Exception $e) {
unlink($tempFile);
throw $e;
}
}
public function retrieve($identifier) {
$tempFile = tempnam(sys_get_temp_dir(), 'storj_');
try {
$this->driver->downloadFile($identifier, $tempFile);
$content = file_get_contents($tempFile);
unlink($tempFile);
return $content;
} catch (\Exception $e) {
unlink($tempFile);
throw $e;
}
}
}
配置文件 config/storj.php:
<?php
return [
// 选择集成方式: 'cli', 's3', 'native'
'driver' => 's3',
// CLI模式
'access_grant' => env('STORJ_ACCESS_GRANT', ''),
// S3兼容模式
'access_key' => env('STORJ_ACCESS_KEY', ''),
'secret_key' => env('STORJ_SECRET_KEY', ''),
'bucket' => env('STORJ_BUCKET', 'default-bucket'),
'endpoint' => 'https://gateway.storjshare.io',
// 通用设置
'encryption' => true,
'cache_ttl' => 3600 // 秒
];
性能优化建议
-
分块上传:
public function uploadLargeFile($localPath, $remotePath, $chunkSize = 5 * 1024 * 1024) { $file = fopen($localPath, 'rb'); $partNumber = 1; while (!feof($file)) { $chunk = fread($file, $chunkSize); $this->uploadChunk($remotePath, $chunk, $partNumber); $partNumber++; } fclose($file); $this->completeMultipartUpload($remotePath); } -
本地缓存:
public function getWithCache($key, $ttl = 3600) { $cacheKey = "storj:{$key}"; $cached = apcu_fetch($cacheKey); if ($cached !== false) { return $cached; } $content = $this->retrieve($key); apcu_store($cacheKey, $content, $ttl); return $content; } -
压缩后上传:
public function uploadCompressed($localPath, $remotePath) { $gzPath = $localPath . '.gz'; file_put_contents($gzPath, gzencode(file_get_contents($localPath))); $result = $this->uploadFile($gzPath, $remotePath); unlink($gzPath); return $result; }
安全注意事项
- 访问凭证管理:
// 使用环境变量而不是硬编码 $accessGrant = getenv('STORJ_ACCESS_GRANT');
// 或使用密钥管理服务 $secretManager = new SecretManager(); $accessGrant = $secretManager->getSecret('storj/access-grant');
2. **数据加密**:
```php
public function encryptAndUpload($data, $key) {
$encrypted = openssl_encrypt(
$data,
'aes-256-gcm',
$this->encryptionKey,
0,
$iv,
$tag
);
return $this->store($key, $iv . $tag . $encrypted);
}
- 访问控制:
// 生成限时访问令牌 $token = $this->storj->generateAccessToken([ 'bucket' => 'specific-bucket', 'prefix' => 'user-123/', 'expires' => time() + 3600, 'permissions' => ['read'] ]);
监控和日志
class StorjMonitored extends StorjClient {
public function store($identifier, $content) {
$startTime = microtime(true);
try {
$result = parent::store($identifier, $content);
$this->logSuccess('store', $identifier, microtime(true) - $startTime);
return $result;
} catch (\Exception $e) {
$this->logFailure('store', $identifier, $e->getMessage());
throw $e;
}
}
private function logSuccess($operation, $identifier, $duration) {
// 记录到日志系统或监控平台
Logger::info("Storj {$operation} successful", [
'identifier' => $identifier,
'duration' => $duration
]);
// 发送指标到监控系统
StatsD::timing("storj.{$operation}", $duration);
}
}
推荐的集成方式
- 小型项目 → CLI方式(简单快速)
- 中型项目 → S3兼容API(标准S3 SDK,功能完整)
- 大型/高性能项目 → Native PHP扩展(性能最优)
- 已有AWS S3代码 → S3兼容模式(最小改动)
根据你的项目规模和需求选择合适的集成方式,建议从S3兼容模式开始,因为它最灵活且易于迁移。