1tomany/data-uri
Parse data URIs, base64 strings, plain text, URLs, or local files into a temporary file via an immutable value object. Auto-detect or override MIME type, set an optional display name, and the temp file is deleted automatically on destruct.
composer require 1tomany/data-uri
use OneToMany\DataUri\DataDecoder;
$decoder = new DataDecoder();
$dataUri = $decoder->decode('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...');
$path = $dataUri->getPathname(); // Temporary file path
$mimeType = $dataUri->getType(); // Auto-detected or explicit MIME type
DataDecoder::decode(): Primary method for handling data URIs, URLs, or files.DataUriInterface: Contract for the returned immutable object (auto-deletes on destruction).$response = Http::get('https://api.example.com/image');
$dataUri = (new DataDecoder())->decode($response->body());
Storage::put('public/uploads/' . $dataUri->getClientName(), file_get_contents($dataUri->getPathname()));
$dataUri = (new DataDecoder())->decode('data:text/plain;base64,SGVsbG8gV29ybGQ=');
$content = file_get_contents($dataUri->getPathname()); // "Hello World"
getPathname() to access the temporary file. The file auto-deletes when $dataUri goes out of scope.$dataUri = (new DataDecoder())->decode('https://example.com/file.pdf');
Storage::disk('s3')->put('remote-files/' . $dataUri->getClientName(), file_get_contents($dataUri->getPathname()));
$dataUri->getClientName().$dataUri = (new DataDecoder())->decodeBase64(
base64_encode(file_get_contents('original.pdf')),
'application/pdf',
'document.pdf'
);
$dataUri = (new DataDecoder())->decodeText('Hello, world!', 'greeting.txt');
.txt if no extension is provided.public function handleUpload(Request $request)
{
$dataUri = (new DataDecoder())->decode($request->file('data_uri'));
$path = $dataUri->getPathname();
$filename = $dataUri->getClientName();
Storage::put("uploads/{$filename}", file_get_contents($path));
// File auto-deletes after use; no manual cleanup needed.
}
class ProcessDataUriJob implements ShouldQueue
{
public function handle()
{
$dataUri = (new DataDecoder())->decode($this->dataUri);
// Process file (e.g., generate thumbnail, analyze content)
$this->afterCompletion(); // File auto-deletes when job finishes
}
}
public function getEmbeddedImage()
{
$dataUri = (new DataDecoder())->decode($this->request->input('image_data_uri'));
return response()->file($dataUri->getPathname())
->header('Content-Type', $dataUri->getType());
}
// In your TinyMCE/CKEditor config:
upload_image: function(blobInfo, success, failure) {
const reader = new FileReader();
reader.onload = function() {
const base64 = reader.result.split(',')[1];
axios.post('/api/upload-data-uri', { dataUri: `data:image/png;base64,${base64}` })
.then(response => success(response.data.url));
};
reader.readAsDataURL(blobInfo.blob());
}
public function uploadDataUri(Request $request)
{
$dataUri = (new DataDecoder())->decode($request->dataUri);
return Storage::url($dataUri->getClientName());
}
$dataUri = (new DataDecoder())->decode($dataUriString, null, 'text/markdown');
// Override auto-detected MIME type
$dataUri = (new DataDecoder())->decode('https://large-file.example.com/data.zip');
$stream = fopen($dataUri->getPathname(), 'r');
while (!feof($stream)) {
$chunk = fread($stream, 8192);
// Process chunk (e.g., stream to S3)
}
fclose($stream); // File auto-deletes
public function validateDataUri($dataUriString)
{
$decoder = new DataDecoder();
try {
$dataUri = $decoder->decode($dataUriString);
// Validate MIME type, size, etc.
if ($dataUri->getType() !== 'image/png') {
throw new \InvalidArgumentException('Invalid MIME type');
}
return $dataUri;
} catch (\Exception $e) {
throw new \InvalidArgumentException('Invalid data URI');
}
}
public function testDataUriHandling()
{
$mockDataUri = 'data:text/plain;base64,SGVsbG8gV29ybGQ=';
$dataUri = (new DataDecoder())->decode($mockDataUri);
$this->assertEquals('Hello World', file_get_contents($dataUri->getPathname()));
$this->assertEquals('text/plain', $dataUri->getType());
}
File Auto-Deletion Timing:
DataUriInterface object is destructed or garbage collected. Ensure the object remains in scope until the file is no longer needed.// Bad: File deletes immediately
(new DataDecoder())->decode($dataUri);
// Good: File persists until $dataUri goes out of scope
$dataUri = (new DataDecoder())->decode($dataUri);
MIME Type Auto-Detection Limitations:
mime_content_type() may return generic types (e.g., text/plain for Markdown). Always specify explicit types when possible.type parameter in DataDecoder::decode():
$dataUri = (new DataDecoder())->decode($dataUriString, null, 'text/markdown');
Large File Memory Issues:
memory_limit. Monitor memory usage in production.memory_limit temporarily.URL Validation:
if (!filter_var($url, FILTER_VALIDATE_URL)) {
throw new \InvalidArgumentException('Invalid URL');
}
Filename Preservation:
$name is not provided, the package generates a random filename. Always pass the original filename when possible:
$dataUri = (new DataDecoder())->decode($dataUriString, 'original.pdf');
Base64 Decoding Errors:
if (!base64_is_valid($base64String)) {
throw new \InvalidArgumentException('Invalid base64');
}
Stream Contexts:
fopen() with default stream contexts. Custom contexts (e.g., proxies, timeouts) require manual setup:
$context = stream_context_create([
'http' => [
'timeout' => 10,
'header' => "User-Agent: MyApp/1.0\r\n",
]
]);
$dataUri = (new DataDecoder())->decode('https://example.com/file', null, null, $context);
How can I help you explore Laravel packages today?