Skip to content

Commit

Permalink
(feat) Add support for uploads via form data
Browse files Browse the repository at this point in the history
This makes it possible to upload the local file directly, without the
need for the file to be public.
  • Loading branch information
nitriques committed Oct 16, 2023
1 parent 7d055b0 commit a2ee9b2
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public function autoUpload(\craft\events\ModelEvent $event)
'elementId' => $asset->id,
'videoUrl' => $asset->getUrl(),
'videoName' => $asset->filename,
'videoPath' => $asset->getFs()->rootPath,
]);
\Craft::$app->getQueue()->push($uploadJob);
}
Expand Down
39 changes: 36 additions & 3 deletions src/client/CloudflareVideoStreamClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace deuxhuithuit\cfstream\client;

use Exception;
use GuzzleHttp;

class CloudflareVideoStreamClient
Expand All @@ -12,15 +13,15 @@ class CloudflareVideoStreamClient
public function __construct(\deuxhuithuit\cfstream\models\Settings $config)
{
if (!$config->getApiToken()) {
throw new \Error('No API token found');
throw new Exception('No API token found');
}
if (!$config->getAccountId()) {
throw new \Error('No account ID found');
throw new Exception('No account ID found');
}
$this->config = $config;
}

public function uploadVideo(string $videoUrl, string $videoName)
public function uploadVideoByUrl(string $videoUrl, string $videoName)
{
$client = new GuzzleHttp\Client();
$accountId = $this->config->getAccountId();
Expand All @@ -46,6 +47,38 @@ public function uploadVideo(string $videoUrl, string $videoName)
return $data['result'];
}

public function uploadVideoByPath(string $videoPath, string $videoFilename)
{
$client = new GuzzleHttp\Client();
$accountId = $this->config->getAccountId();
$apiToken = $this->config->getApiToken();
$url = $this->baseUrl . $accountId . '/stream';
$uploadRes = $client->request('POST', $url, [
'headers' => [
'Authorization' => 'Bearer ' . $apiToken,
],
'multipart' => [
[
'name' => 'file',
'contents' => fopen($videoPath . '/' . $videoFilename, 'r'),
'filename' => $videoFilename,
]
],
'http_errors' => false,
]);

if ($uploadRes->getStatusCode() !== 200) {
return [
'error' => 'Error uploading video',
'message' => $uploadRes->getBody(),
];
}

$data = json_decode($uploadRes->getBody(), true);

return $data['result'];
}

public function getVideo(string $videoUid)
{
$client = new GuzzleHttp\Client();
Expand Down
1 change: 1 addition & 0 deletions src/controllers/ReuploadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public function actionReupload(): int
'elementId' => $asset->id,
'videoUrl' => $asset->getUrl(),
'videoName' => $asset->title ?? $asset->filename,
'videoPath' => $asset->getFs()->rootPath,
]);
\Craft::$app->getQueue()->push($uploadJob);
++$uploadCount;
Expand Down
1 change: 1 addition & 0 deletions src/controllers/UploadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public function actionUpload()
'elementId' => $elementId,
'videoUrl' => $videoUrl,
'videoName' => $videoName,
'videoPath' => $asset->getFs()->rootPath,
]);
\Craft::$app->getQueue()->push($uploadJob);
$element->setFieldValue($fieldHandle, ['readyToStream' => false]);
Expand Down
5 changes: 5 additions & 0 deletions src/jobs/DeleteVideoJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ class DeleteVideoJob extends BaseJob
public $elementId;
public $videoUid;

public function getTtr()
{
return 30; // 30 seconds
}

public function execute($queue): void
{
$this->setProgress($queue, 0, 'Validating job data');
Expand Down
12 changes: 11 additions & 1 deletion src/jobs/PollVideoJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ class PollVideoJob extends BaseJob
public $lastResult;
public $attempts = 0;

private function delay()
{
return $this->attempts * 2;
}

public function getTtr()
{
return 10 + $this->delay();
}

public function execute($queue): void
{
$this->setProgress($queue, 0, 'Validating job data');
Expand Down Expand Up @@ -80,7 +90,7 @@ public function execute($queue): void
$this->setProgress($queue, 0, 'Delayed retry');
// Retry the job after x * 2 seconds
$this->lastResult = $result;
$queue->delay($this->attempts * 2)->push($this);
$queue->delay($this->delay())->push($this);
}
}

Expand Down
13 changes: 11 additions & 2 deletions src/jobs/UploadVideoJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use craft\queue\BaseJob;
use deuxhuithuit\cfstream\client\CloudflareVideoStreamClient;
use deuxhuithuit\cfstream\fields\CloudflareVideoStreamField;
use deuxhuithuit\cfstream\models\Settings;

// TODO: Make cancellable, to cancel the upload if the asset is deleted
class UploadVideoJob extends BaseJob implements \yii\queue\RetryableJobInterface
Expand All @@ -13,6 +14,7 @@ class UploadVideoJob extends BaseJob implements \yii\queue\RetryableJobInterface
public $elementId;
public $videoUrl;
public $videoName;
public $videoPath;

public function getTtr()
{
Expand Down Expand Up @@ -55,8 +57,15 @@ public function execute($queue): void

$this->setProgress($queue, 0.2, 'Uploading video to Cloudflare Stream');

$client = new CloudflareVideoStreamClient(\deuxhuithuit\cfstream\Plugin::getInstance()->getSettings());
$result = $client->uploadVideo($this->videoUrl, $this->videoName);
/** @var Settings */
$settings = \deuxhuithuit\cfstream\Plugin::getInstance()->getSettings();
$client = new CloudflareVideoStreamClient($settings);
$result = null;
if ($settings->isUsingFormUpload()) {
$result = $client->uploadVideoByPath($this->videoPath, basename($this->videoUrl));
} else {
$result = $client->uploadVideoByUrl($this->videoUrl, $this->videoName);
}

$this->setProgress($queue, 0.3, 'Uploading request returned');

Expand Down
11 changes: 10 additions & 1 deletion src/models/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@ class Settings extends Model
{
public $accountId = '';
public $apiToken = '';

/**
* @var bool
*/
public $autoUpload = false;
/**
* @var bool
*/
public $useFormUpload = false;

public function defineRules(): array
{
return [
[['accountId', 'apiToken'], 'required'],
['autoUpload', 'boolean'],
['useFormUpload', 'boolean']
];
}

Expand All @@ -37,4 +41,9 @@ public function isAutoUpload(): bool
{
return $this->autoUpload == 1 || $this->autoUpload == true;
}

public function isUsingFormUpload(): bool
{
return $this->useFormUpload == 1 || $this->useFormUpload == true;
}
}
8 changes: 8 additions & 0 deletions src/templates/settings.twig
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@
name: 'autoUpload',
on: settings.autoUpload,
}) }}

<br/>

{{ forms.lightswitch({
label: 'Upload videos to Cloudflare Stream usign form data instead of via the asset`s url'|t('cloudflare-stream'),
name: 'useFormUpload',
on: settings.useFormUpload,
}) }}

0 comments on commit a2ee9b2

Please sign in to comment.