Skip to content

Instantly share code, notes, and snippets.

@aaronbushnell
Last active October 15, 2025 10:24
Show Gist options
  • Save aaronbushnell/91dd215930ffcb8fdcbb42fe368b5634 to your computer and use it in GitHub Desktop.
Save aaronbushnell/91dd215930ffcb8fdcbb42fe368b5634 to your computer and use it in GitHub Desktop.
A helper class to create Statamic assets out of URLs. Uses intervention/image for compression and resizing
<?php
namespace App\Helpers;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\ImageManagerStatic as Image;
use Statamic\Contracts\Assets\AssetContainer;
use Statamic\Facades\Asset;
class AssetImport
{
protected string $url;
protected AssetContainer $container;
protected ?string $path = null;
protected ?array $data = [];
protected ?int $quality = null;
protected ?int $height = null;
protected ?int $width = null;
protected bool $replace = false;
/**
* The URL of the asset to download and store
*/
public static function fromUrl(string $url): self
{
$self = new self;
$self->url = $url;
return $self;
}
/**
* The handle of the Statamic container to use for the file upload
*/
public function container(string $container): self
{
$this->container = \Statamic\Facades\AssetContainer::findOrFail($container);
return $this;
}
/**
* The path to use for the locally-stored asset. This will default to the filename of the source URL if not supplied.
* Ex: `my-folder/filename.jpg`
*/
public function path(string $path): self
{
$this->path = $path;
return $this;
}
/**
* For images, set a quality level from `1-100` to compress images before saving.
*/
public function quality(int $quality): self
{
$this->quality = max(1, min(100, $quality));
return $this;
}
/**
* For images, supply a height, width, both, or neither to resize them before saving
*/
public function resize(?int $width, ?int $height): self
{
$this->width = $width;
$this->height = $height;
return $this;
}
/**
* Additional data to pass to Statamic when creating the asset
* Ex: `["alt" => "An alt description"]`
*/
public function data(array $data): self
{
$this->data = $data;
return $this;
}
/**
* Replaces an existing file at the specified path if it exists
*/
public function replaceExisting(): self
{
$this->replace = true;
return $this;
}
/**
* Adds the file the appropriate storage disk and creates a Statamic asset for it
*/
public function create(): void
{
if (! $this->replace && Storage::disk($this->container->disk)->exists($this->getPath())) {
throw new \Exception("The file at path [{$this->getPath()}] already exists in the [{$this->container->handle()}] container.");
}
// Get the file blob from the URL and store it in the specified container and folder
$blob = Http::get($this->url)->throw();
Storage::disk($this->container->disk)->put($this->getPath(), $blob);
// If we need to resize or compress the image, we'll do that now
if ($this->quality || $this->width || $this->height) {
$image = Image::make(Storage::disk($this->container->disk)->path($this->getPath()));
// Resize the image if necessary while preserving the aspect ratio and not allowing it to be upsized
if ($this->width || $this->height) {
$image->resize($this->width, $this->height, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
}
// Save the image with the specified quality
$image->save(null, $this->quality);
}
// Create the asset in Statamic
Asset::make()
->container($this->container->handle())
->path($this->getPath())
->data($this->data)
->save();
}
/**
* Creates a relative path for the uploaded asset using the one set by the user or the original filename
*/
protected function getPath(): string
{
return $this->path ? $this->path : basename($this->url);
}
}
<?php
use App\Helpers\AssetImport;
// Take an image, rename it, apply alt text, resize it, and compress it. Replace any existing versions
AssetImport::fromUrl("https://example.com/path/to/an/image.jpg")
->container('uploads')
->path('headshots/john-smith.jpg')
->data(['alt' => 'John Smith'])
->resize(800, 800)
->quality(80)
->replaceExisting()
->create();
// Creates a report.pdf in the root of the uploads container
AssetImport::fromUrl("https://example.com/report.pdf")
->container('uploads')
->create();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment