function for uploading video
VideoController.php
public function post_video_details(Request $request)
{
$uploadedFile = $request->file('file');
$without_extension = pathinfo($uploadedFile->getClientOriginalName(), PATHINFO_FILENAME); // getting only file name without extension to make it slugify
$extension = $uploadedFile->getClientOriginalExtension();
$without_extension = str_slug($without_extension); // make slugify only name
$filename = time().$without_extension.'.'.$extension; // time() + name + . + extension
Storage::disk('local')->putFileAs(
'public/uploads/',
$uploadedFile,
$filename
);
// putFileAs take 3 parameters. 1.folder, 2.file 3.my_desired_filename
Video::create([
'title' => $request->title,
'video' => $filename,
'user_id' => auth()->id(),
]); // adding info to the database
return response()->json([
'success' => 'Video Details update successfully',
]);
}
transforming single instance in model for api response
Video.php
<?php
namespace App;
use App\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class Video extends Model
{
protected $guarded = [];
protected $appends = ['video_url'];
public function getVideoUrlAttribute() {
return url( Storage::url('uploads/'.$this->video));
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Here we append video_url
as a properties. Properties value will be resolved by getVideoUrlAttribute
.
vue component for showing and uploading content
Video.vue html part
<template>
<transition name="fade">
<div class='video_block'>
<div class='card'>
<div class='card-header'>
Videos
</div>
<div class='card-body'>
<h3 class="my-4"> <span class='text-dark'>Introduction Video. </span> Introduce yourself and tell others about what you are looking for?</h3>
<div class="form-group image-div">
<input
id="image_upload"
name="image"
v-on:change="handleFileChange()"
accept="video/mp4,video/x-m4v,video/*"
ref="file"
placeholder=""
type="file">
<label id="image_upload_label" for="image_upload"><i class="fa fa-file-video-o" aria-hidden="true"></i> Upload a Video</label>
</div>
<div>
<label v-if="formErrors.file" class='d-block text-danger'>Video is required</label>
</div>
<div v-if="file" class='form-group'>
<p>{{file.name}} <span @click="removeFile" class="span_times"><i class='fa fa-times'></i></span></p>
</div>
<div class='form-group mt-4'>
<label for='video_title'>Video title</label>
<input v-model="title" type='text' class='form-control' name='video_title' id='video_title'/>
<label v-if="formErrors.title" class='d-block text-danger'>title is required</label>
</div>
<div class='row'>
<div class='col-md-12'>
<div class="d-flex justify-content-end mt-3">
<button v-if="!loading" class="btn btn-warning mr-3" @click="resetForm">
Reset
</button>
<button v-if="!loading" class="btn btn-primary" @click="handleSubmit">
Save
</button>
<button v-if="loading" class='btn btn-primary'>
<i class="fa fa-circle-o-notch fa-spin" style="font-size:24px"></i>
{{uploadPercentage.toFixed(2)}}%
</button>
</div>
</div>
</div>
</div>
</div>
<div class='card mt-4'>
<div class='card-header'>
<h2>My videos</h2>
</div>
<!-- /.card-header -->
<div class='card-body'>
<div v-if="videos.length" class='row'>
<div v-for="item in videos" class='col-md-6'>
<div class='card m-2'>
<div class='card-body mx-auto'>
<h5>{{item.title}}</h5>
<div>
<video width='100%' controls :src='item.video_url'></video>
</div>
<div class="d-flex justify-content-center mt-3">
<button @click="delete_video_item(item.id)" class="btn btn-danger">delete</button>
</div>
</div>
</div>
</div>
</div>
<p v-if="!videos.length">You haven't upload any video yet</p>
<!-- /.row -->
</div>
</div>
<!-- /.card -->
</div>
</transition>
</template>
Video.vue js part
export default {
data() {
return {
file: '',
title: '',
loading: false,
formErrors: {},
success: false,
error: false,
uploadPercentage: 0,
videos: [],
edit_id: '',
edit_mode: false,
}
},
mounted() {
this.get_video_details();
},
methods: {
handleFileChange() {
this.file = this.$refs.file.files[0];
},
removeFile() {
// this.file.splice( 0, 1 );
this.file = '';
},
videoLink(sub) {
return `http:${app_domain}/${sub}`
},
resetForm() {
this.file = '';
this.title = '';
this.loading= false;
this.formErrors= {};
this.success= false;
this.error= false;
this.uploadPercentage= 0;
this.edit_mode = false;
this.edit_id= '';
},
handleSubmit() {
let title_error = this.check_form_error('title')
let file_error = this.check_form_error('file')
console.log('title_error', title_error)
console.log('file_error', file_error)
if (title_error || file_error) {
return;
}
let formData = new FormData();
formData.append('file', this.file);
formData.append('title', this.title);
let video_post_url = `${app_domain}/json/post_video_details`;
this.loading = true;
axios.post(video_post_url, formData,
{
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: ( progressEvent ) => {
this.uploadPercentage = parseInt( Math.round( ( progressEvent.loaded * 100 ) / progressEvent.total ) );
}
}
).then(response =>{
console.log('response inside success', response)
this.resetForm();
this.get_video_details();
})
.catch(response => {
console.log('error response', response)
});
},
check_form_error(key) {
if (!this[key]) {
this.formErrors = {
...this.formErrors,
[key]: true,
}
return true;
}else {
this.formErrors = {
...this.formErrors,
[key]: false,
}
return false;
}
},
edit_or_post() {
// not using
if ( this.check_form_error('exam')) {
return;
}
this.loading = true;
if (this.edit_mode) {
this.update_video_item();
}else {
this.post_video_details();
}
},
get_video_details () {
axios.get(`${app_domain}/json/get_video_details`).then(response => {
this.videos = response.data;
})
},
post_video_details () {
// not using
let video_post_url = `${app_domain}/json/post_video_details`;
axios.post(video_post_url, this.video).then(response => {
console.log('response', response);
this.loading = false;
this.resetForm();
this.get_video_details();
if (response.data.error) {
this.error = true;
}else {
this.success = true;
}
})
},
update_video_item () {
// not using
let video_update_url = `${app_domain}/json/update_video_item/${this.edit_id}`;
axios.put(video_update_url, this.video).then(response => {
console.log('response', response);
this.loading = false;
this.edit_mode = false;
this.resetForm();
this.get_video_details();
if (response.data.error) {
this.error = true;
}else {
this.success = true;
}
})
},
edit_video_item(id) {
// not using
let video = this.video_collection.find(video => video.id === id);
this.video = {...video};
this.edit_mode = true;
this.edit_id = video.id;
},
delete_video_item(id) {
axios.delete(`${app_domain}/json/delete_video_item/${id}`).then(response => {
this.get_video_details();
})
},
},
}
export default {
data() {
return {
file: '',
title: '',
loading: false,
formErrors: {},
success: false,
error: false,
uploadPercentage: 0,
videos: [],
edit_id: '',
edit_mode: false,
}
},
mounted() {
this.get_video_details();
},
methods: {
handleFileChange() {
this.file = this.$refs.file.files[0];
},
removeFile() {
// this.file.splice( 0, 1 );
this.file = '';
},
videoLink(sub) {
return `http:${app_domain}/${sub}`
},
resetForm() {
this.file = '';
this.title = '';
this.loading= false;
this.formErrors= {};
this.success= false;
this.error= false;
this.uploadPercentage= 0;
this.edit_mode = false;
this.edit_id= '';
},
handleSubmit() {
let title_error = this.check_form_error('title')
let file_error = this.check_form_error('file')
console.log('title_error', title_error)
console.log('file_error', file_error)
if (title_error || file_error) {
return;
}
let formData = new FormData();
formData.append('file', this.file);
formData.append('title', this.title);
let video_post_url = `${app_domain}/json/post_video_details`;
this.loading = true;
axios.post(video_post_url, formData,
{
headers: {
'Content-Type': 'multipart/form-data'
},
onUploadProgress: ( progressEvent ) => {
this.uploadPercentage = parseInt( Math.round( ( progressEvent.loaded * 100 ) / progressEvent.total ) );
}
}
).then(response =>{
console.log('response inside success', response)
this.resetForm();
this.get_video_details();
})
.catch(response => {
console.log('error response', response)
});
},
check_form_error(key) {
if (!this[key]) {
this.formErrors = {
...this.formErrors,
[key]: true,
}
return true;
}else {
this.formErrors = {
...this.formErrors,
[key]: false,
}
return false;
}
},
edit_or_post() {
// not using
if ( this.check_form_error('exam')) {
return;
}
this.loading = true;
if (this.edit_mode) {
this.update_video_item();
}else {
this.post_video_details();
}
},
get_video_details () {
axios.get(`${app_domain}/json/get_video_details`).then(response => {
this.videos = response.data;
})
},
post_video_details () {
// not using
let video_post_url = `${app_domain}/json/post_video_details`;
axios.post(video_post_url, this.video).then(response => {
console.log('response', response);
this.loading = false;
this.resetForm();
this.get_video_details();
if (response.data.error) {
this.error = true;
}else {
this.success = true;
}
})
},
update_video_item () {
// not using
let video_update_url = `${app_domain}/json/update_video_item/${this.edit_id}`;
axios.put(video_update_url, this.video).then(response => {
console.log('response', response);
this.loading = false;
this.edit_mode = false;
this.resetForm();
this.get_video_details();
if (response.data.error) {
this.error = true;
}else {
this.success = true;
}
})
},
edit_video_item(id) {
// not using
let video = this.video_collection.find(video => video.id === id);
this.video = {...video};
this.edit_mode = true;
this.edit_id = video.id;
},
delete_video_item(id) {
axios.delete(`${app_domain}/json/delete_video_item/${id}`).then(response => {
this.get_video_details();
})
},
},
}
Video.vue css part
input#image_upload {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.image-div {}
input#image_upload + label {
font-size: 1.25em;
cursor: pointer;
font-weight: 700;
color: #005da2;
padding: 5px;
background-color: transparent;
border: 1px solid #c8c8c8;
width: 100%;
display: block;
text-align: center;
}
input#image_upload:focus + label {}
input#image_upload + label:hover {
background-color: #c8c8c8;
color: white;
}
#image_upload + label * {
pointer-events: none;
}
button.submit {
background: #379e01;
color: white;
border: none;
padding: 5px 10px;
outline: none;
}
#selectedFiles li {
color: gray;
font-size: 14px;
}
#selectedFiles li span{
padding-left: 20px;
cursor: pointer;
display: inline-block;
}
#selectedFiles li span:hover{
color: tomato;
}
.span_times{
color: #e43226;
cursor: pointer;
font-size: 23px;
position: relative;
top: 4px;
left: 4px;
}