CookieMonster's avatar

How to upload video?

I want to allow user to choose to update a normal post, an image or video. So far, I can upload post and image and they both hit the same controller.

thread controller:

  public function store(Request $request){
          //create thread for post
            if($request->has('post')){
                //validate the request
                $this->validate($request,[
                    'title' => 'required',
                    'body' => 'required',
                    'channel_id' => 'required|exists:channels,id'
                ]);

                //Create a new instance of thread  
                $thread = Thread::create([
                    'user_id' => auth()->id(),
                    'channel_id' => request('channel_id'),
                    'title' => request('title'),
                    'body' => request('body')
                    ]);
                    
                // Success new thread created
                Session::flash('message', 'Thread has been published');
                return redirect($thread->path());

        }
        

        //create thread for image/video
        if($request->has('image')){
            //check if request has image
            if($request->hasFile('image')){
              //check if image is valid uploaded
              if($request->file('image')->isValid()){

                $validated = $request->validate([  
                    'title' => 'required',
                    'channel_id' => 'required|exists:channels,id',    
                    'image' => 'required|mimes:jpeg,png,jpg|max:1014',
                ]);

                $image = $request->file('image');
                $filename = time() . '.' . $image->getClientOriginalExtension();
                Image::make($image)->resize(500,500)->save(public_path('/images/uploads/threads/images/'. $filename));       
           
                //create new post 
                $thread = Thread::create([
                    'user_id' => auth()->id(),
                    'channel_id' => request('channel_id'),
                    'title' => request('title'),
                    'image' => $filename
                     ]);

                 // Success new thread created
                Session::flash('message', 'Thread has been published');
                return redirect($thread->path());
             }        
          return back()->with('error-image','Image is not valid');
         }
        
      }
      return back()->with('error-image','Please upload an image');
            
    }

However, how do I go about the validation rules to validate what video files and size it can fit?

Or should I create a separate controller just for uploading video?

What's the best way to handle this?

0 likes
4 replies
martinbean's avatar

@nickywan123 You will need to use multi-part uploading to upload a video file given they tend to be large files. If you try and upload this in a “normal” HTTP request, then you will either hit timeout or memory limit errors.

CookieMonster's avatar

So should I separate the controller logic for handling video upload?

martinbean's avatar

You should have a separate endpoint that accepts the video file chunks, yes. Once the video file has been transferred to the server in its entirety, you can use the path for creating a post if that’s how posts work in your application.

So if a user selects to upload a video, disable the form until the video’s been uploaded to your server, and then re-enable the form and set the path in a hidden input once you have the path to the video.

CookieMonster's avatar

Well this is how my form looks like:

 <div class="card">
                <div class="card-header">Create a new thread.</div>
                <ul class="nav nav-tabs mt-1">
                    <li class="nav-item">
                        <a href="" data-target="#post" data-toggle="tab" class="nav-link {{ count($errors)|| Session::has('error-image') ? '' : 'active'}} ">Post</a>
                    </li>               
                    <li class="nav-item">
                        <a href="" data-target="#image" data-toggle="tab" class="nav-link {{ $errors->has('image')||Session::has('error-image') ? 'active' : ''}}">Image & Video</a>
                    </li>
        
                </ul>
             <div class="tab-content">
                <!-- Post tab -->
                <div class="tab-pane card-body mt-1 {{count($errors) || Session::has('error-image') ? '' : 'active'}}" id="post">
                    <form method="POST" action="/threads">
                        @csrf
                        <div class="form-group" >
                            <input type="hidden" name="post" value="post">
                            <label for="channel_id">Select A Channel:</label>
                            <select name="channel_id" id="channel_id" class="form-control @error('channel_id') is-invalid @enderror" required>
                                <option value="">Choose one.....</option>
                                @foreach($channels as $channel)
                                 <option value="{{$channel->id}}" {{old('channel_id') == $channel->id ? 'selected' : ''}}>
                                    {{$channel->name}}</option>
                                @endforeach
                            </select>
                        </div>
                        @error('channel_id')
                        <div class="alert alert-danger">{{ $message }}</div>
                        @enderror
                        <div class="form-group">
                            <label for="title">Title:</label>
                            <input type="title" name="title" class="form-control @error('title') is-invalid @enderror" id="title" placeholder="Title" value="{{old('title')}}" required>
                        </div>
                        @error('title')
                        <div class="alert alert-danger">{{ $message }}</div>
                        @enderror
                        <div class="form-group">
                            <label for="body">Body</label>
                            <textarea class="form-control @error('body') is-invalid @enderror" id="body" name="body" rows="8" placeholder="Enter your text" required >{{old('body')}}</textarea>
                        </div>
                        @error('body')
                        <div class="alert alert-danger">{{ $message }}</div>
                        @enderror
                        <div class="form-group">
                            <button type="submit" class="btn btn-primary">Publish</button>
                        </div>
    
                    </form>
                </div>
                <!--Upload image/video tab -->
                 <div class="tab-pane card-body mt-1 {{ $errors->has('image') || Session::has('error-image') ? 'active' : ''}}" id="image">
                    <form method="POST" enctype="multipart/form-data" action="/threads">
                        @csrf
                        <div class="form-group">
                            <label for="channel_id">Select A Channel:</label>
                            <select name="channel_id" id="channel_id" class="form-control" required>
                                <option value="">Choose one.....</option>
                                @foreach($channels as $channel)
                                 <option value="{{$channel->id}}" {{old('channel_id') == $channel->id ? 'selected' : ''}}>
                                    {{$channel->name}}</option>
                                @endforeach
                            </select>
                        </div>

                        <div class="form-group">
                            <label for="title">Title:</label>
                            <input type="title" name="title" class="form-control" id="title" placeholder="Title" value="{{old('title')}}" required>
                        </div>
                        <div class="form-group">
                            <p>Upload a image/video</p>   
                            <input type="file" name="image" accept="image/*" class="@error('image') is-invalid @enderror">
                            @error('image')
                            <div class="alert alert-danger">{{ $message }}</div>
                            @enderror
                            @if (session('error-image'))
                            <div class="alert alert-danger">
                              {{ session('error-image') }}
                            </div>
                            @endif
                        </div>
                        <div class="form-group">
                            <button type="submit" class="btn btn-primary">Publish</button>
                        </div>
                    </form>
                </div>

.....

Though of sharing the same form for image & video but that does not sound good way of doing it. How does multi part uploading will look like in my case?

Please or to participate in this conversation.