=== Rediafile Developer Portal — VPS / Apache deployment package ===
Preset: Apache 2.4 + PHP 8.2 — Production VPS
----------------------------------------------------------------------
## 1. Apache VirtualHost (sites-available/rediafile.conf)
ServerName portal.example.com
DocumentRoot /var/www/rediafile-php/public
DirectoryIndex index.php
AllowOverride All
Require all granted
Options -Indexes +FollowSymLinks
# Deny access to application files outside /public
Require all denied
ErrorLog ${APACHE_LOG_DIR}/rediafile-portal_error.log
CustomLog ${APACHE_LOG_DIR}/rediafile-portal_access.log combined
## 2. .htaccess (place in the web root)
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/assets/ [NC]
RewriteRule ^ - [L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^ index.php [QSA,L]
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
Header set Access-Control-Allow-Headers "Content-Type, Authorization"
php_value upload_max_filesize 10240M
php_value post_max_size 10240M
php_value max_execution_time 3600
php_value max_input_time 3600
php_value memory_limit 512M
## 3. php.ini directives (or conf.d/rediafile.ini)
; Rediafile Developer Portal — php.ini tuning for 10GB uploads
upload_max_filesize = 10240M
post_max_size = 10240M
max_execution_time = 3600
max_input_time = 3600
memory_limit = 512M
max_file_uploads = 100
; Production error handling
display_errors = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_NOTICE
log_errors = On
; Session security
session.cookie_httponly = 1
session.cookie_samesite = "Lax"
session.use_strict_mode = 1
; OPcache (recommended)
opcache.enable = 1
opcache.memory_consumption = 128
opcache.max_accelerated_files = 10000
## 4. PHP SDK — RediafileClient class (src/RediafileClient.php)
tokenFile = \$tokenCacheFile ?? sys_get_temp_dir() . '/rediafile_token.json';
}
/** Authenticate and cache the token. */
public function authorize(): string
{
$cached = $this->loadCachedToken();
if ($cached !== null) {
$this->token = $cached;
return $cached;
}
$resp = $this->sendRequest('/authorize', 'POST', [
'username' => $this->username,
'password' => $this->password,
], false);
$data = json_decode($resp, true);
$this->token = $data['data']['access_token'] ?? '';
$this->saveCachedToken($this->token, $data['data']['expires_in'] ?? 86400);
return $this->token;
}
/** Upload a local file via multipart/form-data. */
public function uploadFile(string $filePath, ?string $folderId = null): array
{
$this->ensureToken();
$params = ['file' => new CURLFile($filePath)];
if ($folderId) {
$params['folder_id'] = $folderId;
}
$resp = $this->sendRequest('/file/upload', 'POST', $params);
return json_decode($resp, true) ?? [];
}
/** Get a signed download URL for a short URL. */
public function getDownloadUrl(string $shortUrl): array
{
$this->ensureToken();
$resp = $this->sendRequest('/file/download', 'GET', ['short_url' => $shortUrl]);
return json_decode($resp, true) ?? [];
}
/** Queue a remote URL for server-to-server upload. */
public function uploadFromRemoteUrl(string $url): array
{
$this->ensureToken();
$resp = $this->sendRequest('/file/url_upload_add', 'POST', ['url' => $url]);
return json_decode($resp, true) ?? [];
}
/** List contents of a folder. */
public function listFolder(string $folderId = 'fld_root'): array
{
$this->ensureToken();
$resp = $this->sendRequest('/folder/listing', 'GET', ['folder_id' => $folderId]);
return json_decode($resp, true) ?? [];
}
/** Create a new folder. */
public function createFolder(string $name, ?string $parentId = null, ?string $password = null): array
{
$this->ensureToken();
$params = ['folder_name' => $name];
if ($parentId) $params['parent_id'] = $parentId;
if ($password) $params['password'] = $password;
$resp = $this->sendRequest('/folder/create', 'POST', $params);
return json_decode($resp, true) ?? [];
}
/* --- internals --- */
private function ensureToken(): void
{
if ($this->token === null) {
$this->authorize();
}
}
private function sendRequest(string $path, string $method, array $params = [], bool $withAuth = true): string
{
$url = $this->baseUrl . $path;
$isGet = strtoupper($method) === 'GET';
$fields = $isGet ? http_build_query($params) : $params;
if ($isGet && $fields) {
$url .= '?' . $fields;
}
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
$headers = ['Accept: application/json'];
if ($withAuth && $this->token) {
$headers[] = 'Authorization: Bearer ' . $this->token;
}
if (!$isGet && $fields) {
// If $fields contains a CURLFile, cURL auto-sets multipart
$hasFile = false;
foreach ($fields as $v) {
if ($v instanceof CURLFile) { $hasFile = true; break; }
}
if (!$hasFile) {
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields));
} else {
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
}
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$resp = curl_exec($ch);
curl_close($ch);
return is_string($resp) ? $resp : '';
}
private function loadCachedToken(): ?string
{
if (!is_file($this->tokenFile)) return null;
$data = json_decode((string) file_get_contents($this->tokenFile), true);
if (!is_array($data)) return null;
if (($data['expires_at'] ?? 0) < time()) return null;
return $data['token'] ?? null;
}
private function saveCachedToken(string \$token, int $expiresIn): void
{
file_put_contents($this->tokenFile, json_encode([
'token' => \$token,
'expires_at' => time() + $expiresIn - 60,
]));
}
}
// --- Usage ---
// $client = new RediafileClient('admin', 'secret123');
// $result = $client->uploadFile('/path/to/large-file.zip');
// print_r($result);