Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jabrij93's avatar

Implementing download multiple files functionality but getting a 404 error ( laravel )

I am trying to implement download all files functionality in my code. I've referred to some links in stackoverflow to implement this. However, I am still struggling to make this works, below are the download controller,

public function downloadDocuments($id)
    {
        $documents = DB::table('product_documents')->where('id', $id)->first();
        $path2 = $documents->file_path;
        $files = array(Storage::url($path2));
        $zip = new ZipArchive();
        $zip_name = time() . "documents.zip"; // Zip name
        $zip->open($zip_name,  ZipArchive::CREATE);
        foreach ($files as $file) {
            echo $path = "public/Product/Documents/" . $file;
            if (file_exists($path)) {
                $zip->addFromString(basename($path),  file_get_contents($path));
            } else {
                echo "file does not exist";
            }
        }
        $zip->close();
    }

Here is the button and route for the download,

<Link href="product-documents.download">
    <span
        className="flex items-center justify-center"
        data-tooltip-id="my-tooltip"
        data-tooltip-content="Download dokumen"
    >
    <DocumentArrowDownIcon className="h-4 w-4" />
    </span>
</Link>
Route::get('/download-documents', [ProductsController::class, 'downloadDocuments'])->name('product-documents.download');

Below are the controller when storing all the documents/images. For experiment, I only want to download multiple files of the documents. I tried again and again but it keeps on failing. Please tell me how can I fix this ? Thank you

public function store(Request $request)
    {
        $data = $this->validate($request, [
            'name' => 'required',
            'description' => 'required|max:150',
            'category_id' => 'required',
            'type_id' => 'required',
            'price' => 'required|numeric|min:0|not_in:0',
            'start_date' => 'required',
            'end_date' => 'required',
            'is_active' => 'required',
            'images.*' => 'image|max:2048', // max file size: 2MB
            'documents.*' => 'file|max:2048', // max file size: 2MB
        ]);

        $product = DB::table('products')
            ->insertGetId([
                'name' => $data['name'],
                'description' => $data['description'],
                'type_id' => $data['type_id'],
                'category_id' => $data['category_id'],
                'price' => $data['price'],
                'start_date' => $data['start_date'],
                'end_date' => $data['end_date'],
                'is_password' => $request['is_password'],
                'is_stamping' => $request['is_stamping'],
                'created_at' => now(),
            ]);

        // handle image uploads
        if ($request->hasFile('images')) {
            $i = 1;
            foreach ($request->file('images') as $image) {
                $name = $request['name'] . '-' . $i;
                $now = new DateTime();
                $fileName = Str::slug($request['name']) . '-' . $now->format('dmYHis') . '-' . $i . '.' . $image->getClientOriginalExtension();
                //$fileName = Str::slug($request['name']) . '-' . time() . '.' . $image->getClientOriginalExtension();
                $path = $image->storeAs('public/Product/Images', $fileName);
                DB::table('product_images')->insert([
                    'product_id' => $product,
                    'name' => $name,
                    'file_path' => Storage::url($path),
                    'created_at' => now(),
                ]);
                $i++;
            }
        }

        // handle document uploads
        if ($request->hasFile('documents')) {
            $i = 1;
            foreach ($request->file('documents') as $document) {
                $name = $request['name'] . '-' . $i;
                $now = new DateTime();
                $fileName = Str::slug($request['name']) . '-' . $now->format('dmYHis') . '-' . $i . '.' . $document->getClientOriginalExtension();
                //$fileName = Str::slug($request['name']) . '-' . time() . '.' . $document->getClientOriginalExtension();
                $path = $document->storeAs('public/Product/Documents', $fileName);
                DB::table('product_documents')->insert([
                    'product_id' => $product,
                    'name' => $name,
                    'file_path' => Storage::url($path),
                    'created_at' => now(),
                ]);
                $i++;
            }
        }

        $now = Carbon::now();
        $month = $now->format('m');
        $year = $now->format('Y');

        DB::table('log_audits')->insert([
            'module_name' => 'Jualan',
            'description' => 'Simpan Produk ' . $data['name'],
            'user_id' => auth()->user()->id,
            'created_at' => $now,
            'month' => $month,
            'year' => $year,
        ]);
        return Redirect::route('produk.index');
    }

At first I tried to implement the Zipper/Chumper method but it's not working since this web app run on laravel 7 instead of laravel 5. So then I did some research and found that I can use ZipArchive. After writing the code and tried to run it. I get the 404 error. I am sure that I may have missed something in my code or probably I wrote and referenced it to the wrong things. Please help

0 likes
1 reply
LaryAI's avatar
Level 58

The issue seems to be with the route definition. The route expects a parameter id, but it is not being passed in the link. Change the link to include the id parameter like this:

<a href="{{ route('product-documents.download', ['id' => $documents->id]) }}">
    <span class="flex items-center justify-center" data-tooltip-id="my-tooltip" data-tooltip-content="Download dokumen">
        <DocumentArrowDownIcon class="h-4 w-4" />
    </span>
</a>

Also, in the downloadDocuments method, the path to the file is being constructed incorrectly. Change this line:

$files = array(Storage::url($path2));

to:

$files = array(public_path($path2));

This should fix the issue.

Please or to participate in this conversation.