PHP项目Storj与分布式存储

wen PHP项目 2

PHP项目与Storj分布式存储集成

Storj是一个去中心化的云存储平台,提供安全、私密的对象存储服务,以下是PHP项目集成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 // 秒
];

性能优化建议

  1. 分块上传

    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);
    }
  2. 本地缓存

    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;
    }
  3. 压缩后上传

    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;
    }

安全注意事项

  1. 访问凭证管理
    // 使用环境变量而不是硬编码
    $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);
}
  1. 访问控制
    // 生成限时访问令牌
    $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);
    }
}

推荐的集成方式

  1. 小型项目 → CLI方式(简单快速)
  2. 中型项目 → S3兼容API(标准S3 SDK,功能完整)
  3. 大型/高性能项目 → Native PHP扩展(性能最优)
  4. 已有AWS S3代码 → S3兼容模式(最小改动)

根据你的项目规模和需求选择合适的集成方式,建议从S3兼容模式开始,因为它最灵活且易于迁移。

抱歉,评论功能暂时关闭!