Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Data Uri Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:
    composer require 1tomany/data-uri
    
  2. Basic Usage:
    use OneToMany\DataUri\DataDecoder;
    
    $decoder = new DataDecoder();
    $dataUri = $decoder->decode('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...');
    
  3. Access File Path:
    $path = $dataUri->getPathname(); // Temporary file path
    $mimeType = $dataUri->getType(); // Auto-detected or explicit MIME type
    

Where to Look First

  • DataDecoder::decode(): Primary method for handling data URIs, URLs, or files.
  • DataUriInterface: Contract for the returned immutable object (auto-deletes on destruction).
  • Examples: decode.php for practical use cases.

First Use Case: Handling Base64 Images from APIs

$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()));

Implementation Patterns

Core Workflows

1. Data URI to Temporary File

$dataUri = (new DataDecoder())->decode('data:text/plain;base64,SGVsbG8gV29ybGQ=');
$content = file_get_contents($dataUri->getPathname()); // "Hello World"
  • Key: Use getPathname() to access the temporary file. The file auto-deletes when $dataUri goes out of scope.

2. Remote URL to File

$dataUri = (new DataDecoder())->decode('https://example.com/file.pdf');
Storage::disk('s3')->put('remote-files/' . $dataUri->getClientName(), file_get_contents($dataUri->getPathname()));
  • Tip: Preserve the original filename with $dataUri->getClientName().

3. Base64 String to File (Non-URI)

$dataUri = (new DataDecoder())->decodeBase64(
    base64_encode(file_get_contents('original.pdf')),
    'application/pdf',
    'document.pdf'
);
  • Use Case: When working with raw base64 strings (e.g., from database fields).

4. Plaintext to File

$dataUri = (new DataDecoder())->decodeText('Hello, world!', 'greeting.txt');
  • Note: Appends .txt if no extension is provided.

Integration with Laravel

1. File Uploads with Original Filenames

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

2. Background Jobs for Async Processing

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

3. API Response Handling

public function getEmbeddedImage()
{
    $dataUri = (new DataDecoder())->decode($this->request->input('image_data_uri'));
    return response()->file($dataUri->getPathname())
        ->header('Content-Type', $dataUri->getType());
}

4. Rich Text Editor Integration

// 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());
}
  • Backend Handler:
    public function uploadDataUri(Request $request)
    {
        $dataUri = (new DataDecoder())->decode($request->dataUri);
        return Storage::url($dataUri->getClientName());
    }
    

Advanced Patterns

1. Custom MIME Type Handling

$dataUri = (new DataDecoder())->decode($dataUriString, null, 'text/markdown');
// Override auto-detected MIME type

2. Stream Processing (Memory-Efficient)

$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

3. Validation Middleware

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

4. Testing with Mocked Data URIs

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

Gotchas and Tips

Pitfalls

  1. File Auto-Deletion Timing:

    • The temporary file deletes when the DataUriInterface object is destructed or garbage collected. Ensure the object remains in scope until the file is no longer needed.
    • Fix: Store the object in a variable or return it from a function to delay deletion.
      // Bad: File deletes immediately
      (new DataDecoder())->decode($dataUri);
      
      // Good: File persists until $dataUri goes out of scope
      $dataUri = (new DataDecoder())->decode($dataUri);
      
  2. MIME Type Auto-Detection Limitations:

    • mime_content_type() may return generic types (e.g., text/plain for Markdown). Always specify explicit types when possible.
    • Tip: Use the type parameter in DataDecoder::decode():
      $dataUri = (new DataDecoder())->decode($dataUriString, null, 'text/markdown');
      
  3. Large File Memory Issues:

    • Streaming is efficient, but very large files (e.g., >100MB) may hit PHP’s memory_limit. Monitor memory usage in production.
    • Workaround: Process files in chunks or increase memory_limit temporarily.
  4. URL Validation:

    • The package does not validate remote URLs (e.g., HTTPS, rate limiting). Add validation before decoding:
      if (!filter_var($url, FILTER_VALIDATE_URL)) {
          throw new \InvalidArgumentException('Invalid URL');
      }
      
  5. Filename Preservation:

    • If $name is not provided, the package generates a random filename. Always pass the original filename when possible:
      $dataUri = (new DataDecoder())->decode($dataUriString, 'original.pdf');
      
  6. Base64 Decoding Errors:

    • Invalid base64 strings will throw exceptions. Validate input before decoding:
      if (!base64_is_valid($base64String)) {
          throw new \InvalidArgumentException('Invalid base64');
      }
      
  7. Stream Contexts:

    • Remote files are fetched using 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);
      

Debugging Tips

  1. Check Temporary File Path:
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony