May Sale! All accounts are 40% off this week.

Sanukdev's avatar

Found 1 error while validating the input provided for the GetObject operation: [Key] expected string length to be >= 1, but found string length of 0

[04:23:55] LOG.error: Found 1 error while validating the input provided for the GetObject operation: [Key] expected string length to be >= 1, but found string length of 0 { "userId": 1, "exception": {} }

I have been able to successfully, locally and in production, upload images to an S3 Spaces bucket with Digital Ocean. My issue is when it comes to deletion. I have an ImageUploadController that works in getting the image up, but I am having a hard time trying to track the path down to Destroy the image. (I am brand new at this so go easy!)

Here is my ImageUploadController upload method to help save it in the bucket

 public function upload(Request $request)
    {
        // Validate the request
        $request->validate([
            'file' => 'required|image|max:2048',
        ]);

        // Store the image in the 'spaces' disk (DigitalOcean Spaces)
        $path = $request->file('file')->store('products/images', 'images');

        // Return the full URL of the uploaded image
        $fullUrl = Storage::disk('images')->url($path);

        // Return response with the full URL
        return response()->json(['path' => $fullUrl]);
    }

Here is the relevant part of the Store method on the ProductsController

// Handle image paths (no file upload, just the paths)
        foreach ($validatedData['images'] as $index => $imagePath) {
            // Determine if the image is the featured image
            $isFeatured = $imagePath === $validatedData['featuredImage'];

            // Save the image path and featured status in the database
            $product->images()->create([
                'path' => $imagePath,
                'featured' => $isFeatured,
            ]);
        }

Here is my Destroy method on my ProductsController.

public function destroy(string $id)
    {
        // Find the product with its images
        $product = Product::with('images')->findOrFail($id);

        // Delete all associated images from the storage
        foreach ($product->images as $image) {
            if (!empty($image->path)) {
                $fullUrl = Storage::disk('images')->url('');
                if (str_starts_with($image->path, $fullUrl)) {
                    $relativePath = str_replace($fullUrl, '', $image->path);
                    
                    // Ensure that the relative path is valid before deleting
                    if (!empty($relativePath)) {
                        Storage::disk('images')->delete($relativePath);
                    } 
                }
            } 
        }
       
        $product->delete();

        // Redirect to the product listing page with a success message
        return redirect()->route('products.index')->with('success', 'Product deleted successfully');
    }

The upload works wonderful. The Destroy, less so.

0 likes
2 replies
LaryAI's avatar
Level 58

The error you're encountering indicates that the Key parameter for the GetObject operation is an empty string. This typically happens when the path to the image is not correctly determined or passed.

Let's break down the solution step-by-step:

  1. Ensure the correct path is stored in the database: When you upload the image, make sure the path stored in the database is relative to the storage disk.

  2. Correctly determine the relative path in the destroy method: When deleting the image, ensure that the relative path is correctly extracted from the full URL.

Here's a revised version of your destroy method:

public function destroy(string $id)
{
    // Find the product with its images
    $product = Product::with('images')->findOrFail($id);

    // Delete all associated images from the storage
    foreach ($product->images as $image) {
        if (!empty($image->path)) {
            // Get the relative path directly from the image path stored in the database
            $relativePath = str_replace(Storage::disk('images')->url(''), '', $image->path);

            // Ensure that the relative path is valid before deleting
            if (!empty($relativePath)) {
                Storage::disk('images')->delete($relativePath);
            }
        }
    }

    // Delete the product from the database (this will automatically delete its variants and images if relationships are set with `cascadeOnDelete`)
    $product->delete();

    // Redirect to the product listing page with a success message
    return redirect()->route('products.index')->with('success', 'Product deleted successfully');
}

Explanation:

  1. Finding the Product: The product is fetched along with its associated images.
  2. Deleting Images: For each image, the relative path is determined by removing the base URL of the storage disk from the stored path. This ensures that the path passed to the delete method is correct.
  3. Deleting the Product: The product is deleted from the database, which should also handle the deletion of related records if cascading is set up correctly.

Additional Tips:

  • Validation: Ensure that the paths stored in the database are correct and relative to the storage disk.
  • Error Handling: Consider adding error handling to manage cases where the image deletion might fail.

By ensuring the relative path is correctly determined and passed to the delete method, you should be able to resolve the error you're encountering.

Sanukdev's avatar

The help Lary gave while well meaning was not helpful in the end...

Please or to participate in this conversation.