LadyDeathKZN's avatar

Route ID to database via controller

Hi all. I have a multiple upload page that has the form that was submitted's id in. My issue is that I can't get the form->id or the id in the route to be submitted on the creation of a file upload in the database. I have tried $id, $form_id, $form->id in the controller and also sending the $form->id in the route when the user uploads but it is not picking it up.

/**
     * Saves the file
     *
     * @param UploadedFile $file
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function saveFile(UploadedFile $file)
    {
        $fileName = $this->createFilename($file);
        $fileAuth = Auth::user()->name;
        // Build the file path
        $filePath = "upload/client/".$fileAuth;
        $finalPath = storage_path("app/".$filePath);
        // Save to Database
        $file = new ClientFormFile;
        $file->filepath = storage_path("app/".$filePath).'/'.$fileName;
        $file->user_id = Auth::user()->id;
        $file->form_id = $form->id;
        $file->save();
        // Move the file name
        $file->move($finalPath, $fileName);
        return response()->json([
            'path' => $filePath,
            'name' => $fileName
        ]);
    }

The above is from pion/laravel-chunk-upload's example, and it works 100%. Had issues getting it to save the filename to the database and now that that is sorted, I can't get the form ID saved.

The user submits a form and then gets sent to:

Route::get('client-upload/upload/{form_id?}', 'ClientUploadController@create')->name('client-upload.create');

Which is like: http://localhost/upload/public/client-upload/upload/2

So the ID is pulling through.

The upload view:

@extends('layouts.app')

@section('content')

<!-- Page Heading -->
<div class="d-sm-flex align-items-center justify-content-between mb-4">
  <h1 class="h3 mb-0 text-gray-800"><i class="text-primary fas fa-plus"></i> Upload</h1>
  <a href="{{ URL::previous() }}" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i class="fas fa-angle-double-left fa-sm text-white-50"></i> Back</a>
</div>

<!-- Content Row -->
<div class="row">
  <div class="col-md-12 col-xs-12 col-lg-12">
    <div class="card shadow mb-4">
      <div class="card-header py-3">
        <div class="clear-fix">
          <div class="float-right">
            <div class="d-flex flex-row bd-highlight">
              <input type="hidden" value="$form->id">
            </div>
          </div>
          <div class="float-left">
            <h6 class="m-0 font-weight-bold text-primary">Upload your file below...</h6>
          </div>
        </div>
      </div>
      <div class="card-body">
        <div class="row">
            <div class="col-md-12 pt-3">
              <div class="text-center" >
                  <div id="resumable-error" style="display: none">
                      Resumable not supported
                  </div>
                  <div id="resumable-drop" style="display: none">
                    <p>
                      <p>
                        <i class="fas fa-caret-square-down fa-3x"></i>
                      </p>
                      <button class="btn btn-dark" id="resumable-browse" data-url="{{ route('cupload', $form->id) }}" >Click here to Upload</button>
                    </p>
                  </div>
                  <ul id="file-upload-list" class="list-unstyled"  style="display: none">

                  </ul>
                  <br/>
              </div>
            </div>
        </div>
    </div>
  </div>
</div>
@endsection

On the route I have tried adding {{route('cupload', $form->id)}} That does not work. The full upload route is:

Route::post('client-upload/upload/{form_id?}', 'ClientUploadController@upload')->name('cupload');

Here is the full controller for the upload:

<?php

namespace App\Http\Controllers;

use App\ClientUpload;
use App\ClientFormFile;
use App\Form;
use Storage;
use Auth;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
use Pion\Laravel\ChunkUpload\Handler\AbstractHandler;
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;

class ClientUploadController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $forms = Form::all();
        return view('uploads.client.index',
        ['forms'=>$forms]
        );
    }

    public function create($id)
    {
        $form = Form::find($id);
        return view('uploads.client.create', [
            'form' => $form
        ]);
    }

    /**
     * Handles the file upload
     *
     * @param Request $request
     *
     * @return \Illuminate\Http\JsonResponse
     *
     * @throws UploadMissingFileException
     * @throws \Pion\Laravel\ChunkUpload\Exceptions\UploadFailedException
     */
    public function upload(Request $request) {
        // create the file receiver
        $receiver = new FileReceiver("file", $request, HandlerFactory::classFromRequest($request));
        // check if the upload is success, throw exception or return response you need
        if ($receiver->isUploaded() === false) {
            throw new UploadMissingFileException();
        }
        // receive the file
        $save = $receiver->receive();
        // check if the upload has finished (in chunk mode it will send smaller files)
        if ($save->isFinished()) {
            // save the file and return any response you need, current example uses `move` function. If you are
            // not using move, you need to manually delete the file by unlink($save->getFile()->getPathname())

            return $this->saveFile($save->getFile());
        }
        // we are in chunk mode, lets send the current progress
        /** @var AbstractHandler $handler */
        $handler = $save->handler();
        return response()->json([
            "done" => $handler->getPercentageDone(),
            'status' => true
        ]);
    }

    /**
     * Saves the file
     *
     * @param UploadedFile $file
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function saveFile(UploadedFile $file)
    {
        $fileName = $this->createFilename($file);
        $fileAuth = Auth::user()->name;
        // Build the file path
        $filePath = "upload/client/".$fileAuth;
        $finalPath = storage_path("app/".$filePath);
        // Save to Database
        $file = new ClientFormFile;
        $file->filepath = storage_path("app/".$filePath).'/'.$fileName;
        $file->user_id = Auth::user()->id;
        $file->form_id = $form->id;
        $file->save();
        // Move the file name
        $file->move($finalPath, $fileName);
        return response()->json([
            'path' => $filePath,
            'name' => $fileName
        ]);
    }
    /**
     * Create unique filename for uploaded file
     * @param UploadedFile $file
     * @return string
     */
    protected function createFilename(UploadedFile $file)
    {
        $extension = $file->getClientOriginalExtension();
        $filename = str_replace(".".$extension, "", $file->getClientOriginalName()); // Filename without extension
        // Add timestamp hash to name of the file
        $filename .= "." . $extension;
        return $filename;
    }

}

The database is as so:

        $table->bigIncrements('id');
            $table->integer('form_id')->unsigned();
            $table->foreign('form_id')->references('id')->on('forms');
            $table->string('filepath');
            $table->integer('user_id')->unsigned();
            $table->foreign('user_id')->references('id')->on('users');

The user_id and filepath works fine, it's just getting the form->id to pass in. Any help would be appreciated!

0 likes
4 replies
Snapey's avatar

how is the file submitted? Form or javascript component?

LadyDeathKZN's avatar

It is done via a JavaScript component:

//Resumable
var $ = window.$; // use the global jQuery instance

var $fileUpload = $('#resumable-browse');
var $fileUploadDrop = $('#resumable-drop');
var $uploadList = $("#file-upload-list");

if ($fileUpload.length > 0 && $fileUploadDrop.length > 0) {
    var resumable = new Resumable({
        // Use chunk size that is smaller than your maximum limit due a resumable issue
        // https://github.com/23/resumable.js/issues/51
        chunkSize: 5 * 5028 * 5028, // 1MB
        simultaneousUploads: 5,
        testChunks: false,
        throttleProgressCallbacks: 1,
        maxFiles: 1,
        // Get the url from data-url tag
        target: $fileUpload.data('url'),
        // Append token to the request - required for web routes
        query:{_token : $('input[name=_token]').val()},

    });

// Resumable.js isn't supported, fall back on a different method
    if (!resumable.support) {
        $('#resumable-error').show();
    } else {
        // Show a place for dropping/selecting files
        $fileUploadDrop.show();
        resumable.assignDrop($fileUpload[0]);
        resumable.assignBrowse($fileUploadDrop[0]);

        // Handle file add event
        resumable.on('fileAdded', function (file) {
            // Show progress bar
            $uploadList.show();
            // Show pause, hide resume
            $('.resumable-progress .progress-resume-link').hide();
            $('.resumable-progress .progress-pause-link').show();
            // Add the file to the list
            $uploadList.append('<li class="resumable-file-' + file.uniqueIdentifier + '">Uploading <span class="resumable-file-name"></span> <span class="resumable-file-progress"></span><br><div class="progress"> <div class="progress-bar" role="progressbar" aria-valuenow="100" aria-valuemax="100"></div> </div><br><div class="alert alert-warning"> When File is "Completed" Proceed to Step 2 </div>');
            $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-name').html(file.fileName);
            // Actually start the upload
            resumable.upload();
        });
        resumable.on('fileSuccess', function (file, message) {
            // Reflect that the file upload has completed
            $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(Completed)');
        });
        resumable.on('fileError', function (file, message) {
            // Reflect that the file upload has resulted in error
            $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html('(file could not be uploaded: ' + message + ')');
        });
        resumable.on('fileProgress', function (file) {
            // Handle progress for both the file and the overall upload
            $('.resumable-file-' + file.uniqueIdentifier + ' .resumable-file-progress').html;
            $('.progress-bar').css({width: Math.floor(resumable.progress() * 100) + '%'});
        });
    }

}

This uses the route: cupload

LadyDeathKZN's avatar

It actually uses both controller and the javascript component with the route

LadyDeathKZN's avatar
LadyDeathKZN
OP
Best Answer
Level 1
<?php

namespace App\Http\Controllers;

use App\ClientUpload;
use App\ClientFormFile;
use App\Form;
use Storage;
use Auth;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Pion\Laravel\ChunkUpload\Exceptions\UploadMissingFileException;
use Pion\Laravel\ChunkUpload\Handler\AbstractHandler;
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;

class ClientUploadController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $forms = Form::all();
        return view('uploads.client.index',
        ['forms'=>$forms]
        );
    }

    public function create($id)
    {
        $form = Form::find($id);
        return view('uploads.client.create', [
            'form' => $form
        ]);
    }

    /**
     * Handles the file upload
     *
     * @param Request $request
     *
     * @return \Illuminate\Http\JsonResponse
     *
     * @throws UploadMissingFileException
     * @throws \Pion\Laravel\ChunkUpload\Exceptions\UploadFailedException
     */
    public function upload(Request $request, $form_id) {
        // create the file receiver
        $receiver = new FileReceiver("file", $request, HandlerFactory::classFromRequest($request));
        // check if the upload is success, throw exception or return response you need
        if ($receiver->isUploaded() === false) {
            throw new UploadMissingFileException();
        }
        // receive the file
        $save = $receiver->receive();
        // check if the upload has finished (in chunk mode it will send smaller files)
        if ($save->isFinished()) {
            // save the file and return any response you need, current example uses `move` function. If you are
            // not using move, you need to manually delete the file by unlink($save->getFile()->getPathname())

            return $this->saveFile($save->getFile(), $form_id);
        }
        // we are in chunk mode, lets send the current progress
        /** @var AbstractHandler $handler */
        $handler = $save->handler();
        return response()->json([
            "done" => $handler->getPercentageDone(),
            'status' => true
        ]);
    }

    /**
     * Saves the file
     *
     * @param UploadedFile $file
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function saveFile(UploadedFile $file, $form_id)
    {
        $fileName = $this->createFilename($file);
        $fileAuth = Auth::user()->name;
        // Build the file path
        $filePath = "upload/client/".$fileAuth;
        $finalPath = storage_path("app/".$filePath);
        // Move the file name
        $file->move($finalPath, $fileName);
        // Save to Database
        $file = new ClientFormFile;
        $file->filepath = storage_path("app/".$filePath).'/'.$fileName;
        $file->user_id = Auth::user()->id;
        $file->form_id = $form_id;
        $file->save();
        return response()->json([
            'path' => $filePath,
            'name' => $fileName
        ]);
    }
    /**
     * Create unique filename for uploaded file
     * @param UploadedFile $file
     * @return string
     */
    protected function createFilename(UploadedFile $file)
    {
        $extension = $file->getClientOriginalExtension();
        $filename = str_replace(".".$extension, "", $file->getClientOriginalName()); // Filename without extension
        // Filename with extension
        $filename .= "." . $extension;
        return $filename;
    }

}

For anyone else in the future

Please or to participate in this conversation.