I am working on file upload with progress bar and cancel button to abort uploading.
I have my upload.html as below,
<div class="row">
<div id="alert-box">{{ msg }}</div>
<div id="image-box"></div>
<div class="col-md-2"><label><b>File :</b></label></div>
<div class="col-md-2"><input type="file" id="fileupload" name="fileupload" required multiple></div>
</div><br>
<div class="container">
<div id="progress-box" class="progress not-visible">
<div class="progress-bar bg-success" role="progessbar" >progress</div>
</div>
</div>
<div id="cancel-box" class="not-visible">
<button id="cancel-btn" class="btn btn-danger">cancel</button>
</div>
and main.js as,
const uploadForm = document.getElementById('upload-form')
const input = document.getElementById('fileupload')
const submitBtn = document.getElementById('submitBtn')
const alertBox = document.getElementById('alert-box')
const progressBox = document.getElementById('progress-box')
const cancelBox = document.getElementById('cancel-box')
const cancelBtn = document.getElementById('cancel-btn')
const csrf = document.getElementsByName('csrfmiddlewaretoken')
$("#upload-form").submit(function(e){
$form = $(this)
var formData = new FormData(this);
const media_data = input.files[0];
if(media_data != null){
console.log(media_data);
progressBox.classList.remove("not-visible");
cancelBox.classList.remove("not-visible");
}
$.ajax({
type: 'POST',
url:'/',
data: formData,
dataType: 'json',
beforeSend: function(){
},
xhr:function(){
const xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>{
if(e.lengthComputable){
const percentProgress = (e.loaded/e.total)*100;
console.log(percentProgress);
progressBox.innerHTML = `<div class="progress-bar progress-bar-striped bg-success"
role="progressbar" style="width: ${percentProgress}%" aria-valuenow="${percentProgress}" aria-valuemin="0"
aria-valuemax="100"></div>`
}
})
cancelBtn.addEventListener('click', e=>{
xhr.abort();
console.log("Abort event");
progressBox.innerHTML="";
progressBox.classList.add("not-visible");
cancelBox.classList.add('not-visible');
})
return xhr
},
success: function(response){
console.log(response);
console.log("successfully upload");
progressBox.classList.add("not-visible");
cancelBox.classList.add("not-visible");
uploadForm.reset();
},
error: function(err){
console.log(err);
},
cache: false,
contentType: false,
processData: false,
});
});
I am trying to abort uploading file when some one click on cancel button which appears when file is uploading.
thought it is setting 'not-visible' class to progress bar and cancel button. file still continue to upload.
any thoughts why it is not stop uploading file on xhr.abort() ?
Thanks,
PB.
Related
When uploading image files, the upload is complete and successful, but when uploading the video file, it is not uploaded and it does not show where the error is
HTML Code:
<div class="row mb-5">
<div class="col-md-12">
<input type="file" name="slider_image" id="" class="form-control mb-5" onchange="homeSliderUpload(this)">
<div class="progress mb-5" style="--sa-progress--value: 0%">
<div class="progress-bar progress-bar-sa-primary" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function homeSliderUpload(form) {
alert("First");
var file_data = $("input[name='slider_image']").prop('files')[0];
var form_data = new FormData();
form_data.append('file', file_data);
$.ajax({
url: "<?php echo base_url(); ?>/Path/VedioUploader",
dataType: 'text',
method: "post",
cache: false,
contentType: false,
processData: false,
data: form_data,
success: function(data) {
var rJson = $.parseJSON(data);
if (rJson.status == true) {
$(".progress").attr("style", "--sa-progress--value: 100%");
$("input[name='slider_image']").val('');
setInterval(() => {
location.reload();
}, 1000);
} else {
alert("Error");
}
}
});
}
php Code ( Ajax Code):
public function VedioUploader()
{
$validateImage = $this->validate([
'file' => [
'uploaded[file]',
'mime_in[file, video/mp4, image/png, image/jpg,image/jpeg, image/gif]',
'max_size[file, 1000000000]',
],
]);
if ($validateImage) {
$imageFile = $this->request->getFile('file');
$folder = "Vedio/";
$fileName = rand(10005, 100005) . time() . ".mp4";
$imageFile->move($folder, $fileName);
$data = [
'img_name' => $imageFile->getClientName(),
'file' => $imageFile->getClientMimeType(),
'type' => $imageFile->getClientExtension(),
];
if ($fileName) {
$homeSliderModel = new VedioUplaod();
$home_slider["slider_file_url"] = $folder . "/" . $fileName;
$home_slider["slider_show"] = 1;
$home_slider["slider_order"] = 0;
$homeSliderModel->insert($home_slider);
if (!$homeSliderModel->errors()) {
echo json_encode([
"status" => true,
"slider_id" => $homeSliderModel->getInsertID(),
"file_url" => $folder . "/" . $fileName,
"order" => 0
]);
}
}
}
}
I tried removing the image types and retrying to upload the images, but it didn't work. It was similar to uploading the video. I thought it was because of the type, but nothing happened.
'mime_in[file, video/mp4]',
I have an issue with a progress upload bar in Django when the site is deployed to Heroku, when I click on the upload button the progress bar shows up at 10% then doesn't change or count up to 100%, when the upload is finished, it redirects as instructed in my views.py , the function runs fine locally, but after deploying to heroku it doesn't work. I think it may be something to do with the deployed url using 'https', but not sure and how to fix it? appreciate any help.
custom.js
function progressBar() {
progressBox.classList.remove('not-visible')
cancelBox.classList.remove('not-visible')
const upload_data = input.files[0]
const url = URL.createObjectURL(upload_data)
// console.log(upload_data);
const fd = new FormData()
fd.append('csrfmiddlewaretoken', csrf[0].value)
fd.append('track', upload_data)
$.ajax({
type: 'POST',
enctype: 'multipart/form-data',
data: fd,
beforeSend: function(){
},
xhr: function(){
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>{
// console.log(e);
if (e.lengthComputable) {
const percent = (e.loaded / e.total) * 100;
// console.log(percent);
progressBox.innerHTML = `<h5 style="text-align:center;">${percent.toFixed(1)}%</h5>
<div class="progress" style="height: 30px;">
<div class="progress-bar bg-success" role="progressbar" style="width: ${percent}%"
aria-valuenow="${percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>`
}
})
cancelBtn.addEventListener('click', ()=>{
xhr.abort()
progressBox.innerHTML=""
cancelBox.classList.add('not-visible')
window.location.reload();
})
return xhr;
},
success: function(response){
// console.log(response);
uploadForm.reset()
cancelBox.classList.add('not-visible')
},
error: function(error){
console.log(error);
},
cache: false,
contentType: false,
processData: false,
})
}
I have already made the progress bar and everything. But I have a problem when I choose the file is upload, that's mean the file is uploading twice, once when choosing the file and one once submit the form, and this bad user experience so I want to show the progress bar only when submitting the form, I use Django in backend and ajax recall
my HTML form
<div id="alert-box"></div>
<form id="upload-form" action="." method="post" enctype="multipart/form-data">
{% csrf_token %}
<div id="progress-box" class="d-none">progress</div>
<div class="custom-file">
<input type="file" class="custom-file-input" id="formGroupExampleInput2" required value="{{V_form.video}}">
<label class="custom-file-label" for="formGroupExampleInput2">Choose Video...</label>
</div>
<div class="custom-file mt-5 mb-4">
<input type="file" class="custom-file-input" id="file2" required value="{{V_form.video_poster}}">
<label class="custom-file-label" for="formGroupExampleInput2">Choose Poster For Your Video...</label>
</div>
<div class="d-flex justify-content-center my-3 px-3" > <button class="btn-block btnn-color" id="heel" name="submit_v_form"> Upload</button></div>
</form>
the javascript-Ajax
const file_input_label = document.getElementById('file_input_label')
function input_filename(){
file_input_label.innerHTML = input.files[0].name;
console.log(file_input_label);
}
const uploadForm = document.getElementById('upload-form')
// const input = document.getElementById('formGroupExampleInput2')
const input = document.getElementById('formGroupExampleInput2')
console.log(input)
const alertBox = document.getElementById('alert-box')
const imageBox = document.getElementById('image-box')
const progressBox = document.getElementById('progress-box')
const canceleBox = document.getElementById('cancel-box')
const canceleBtn = document.getElementById('cancel-btn')
const csrf = document.getElementsByName('csrfmiddlewaretoken')
// whenever choose th file something happen
input.addEventListener('change', ()=>{
progressBox.classList.remove('d-none')
canceleBox.classList.remove('d-none')
var filePath = input.value;
var allowedTypes = /(\.mp4|\.mkv|\.avi|\.flv)$/i;
if(!allowedTypes.exec(filePath)){
alertBox.innerHTML = `<div class="alert alert-danger" role="alert">Please Upload the valid file type</div>`
input.value = "";
return false;
}
const img_data = input.files[0]
const url = URL.createObjectURL(img_data)
console.log(img_data)
const fd = new FormData()
fd.append('csrfmiddlewaretoken', csrf[0].value)
fd.append('video', img_data)
$.ajax({
type: 'POST',
url: uploadForm.action,
enctype: 'multipart/form-data',
data: fd,
beforeSend: function() {
console.log('before')
alertBox.innerHTML = ""
// imageBox.innerHTML = ""
},
xhr: function() {
const xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', e=>{
// console.log(e)
if (e.lengthComputable){
const percent = e.loaded / e.total * 100
console.log(percent);
progressBox.innerHTML =
`<div class="progress">
<div class="progress-bar" role="progressbar" style="width: ${percent}%" aria-valuenow=" ${percent}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<p>${percent.toFixed(1)}%</p>`
}
})
canceleBtn.addEventListener('click', ()=>{
xhr.abort()
setTimeout(()=>{
uploadForm.reset()
progressBox.innerHTML = ""
alertBox.innerHTML = ""
canceleBox.classList.add('d-none')
}, 1000)
})
return xhr
},
success: function(response) {
console.log(response)
// imageBox.innerHTML = `<img src="${url}" width="300px">`
// imageBox.innerHTML = `<video class="card" controls src="${url}">`
alertBox.innerHTML = `<div class="alert alert-success" role="alert">Successfully uploaded your video. click upload to upload your video</div>`
},
error: function(error){
console.log(error)
alertBox.innerHTML = `<div class="alert alert-danger" role="alert">Ups something went wrong!</div>`
},
cache: false,
contentType: false,
processData: false,
})
})
I think what you are trying to achieve here is to show the progress bar only on Ajax submit. So you can just add/remove the display-none class on each operational methods as below.
input.addEventListener('change', () => {
progressBox.classList.add('d-none') // Though this class is already added in html [seems redundant here].
$.ajax({
type: 'POST',
beforeSend: function() {
progressBox.classList.remove('d-none')
},
success: function(response) {
progressBox.classList.add('d-none')
},
error: function(error) {
progressBox.classList.add('d-none')
})
}
Hope this will be one way to work around but let me know if this solves your problem.
I am trying to create a dummy progress bar that is initiated when the user clicks the submit button, and then disappears when the data is returned.
I would like it to load a little bit to a certain point to show the user that the data is being returned, and then complete once the data is rendered.
Any advice on how I could achieve this?
Here is my bootstrap progress bar template:
<div id="loadingcontainer">
<div class="progress" style="height: 5px;">
<div id="myprogress" class="progress-bar" style="color:#EB7051;" style="background-color: #ffffff" role="progressbar" style="width: 25%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
Here is my script tag:
function searchIt() {
let form = document.querySelector('form')
console.log(form)
form.addEventListener('submit', async(e) => {
e.preventDefault()
let urlIN = form.url.value
let url = encodeURIComponent(urlIN)
console.log(url)
try {
const data = await fetch('/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: url
})
}).then(res => {
document.open()
res.text().then(function(text) {
document.write(text)
});
})
} catch (err) {
console.error(err)
}
})
I am new to ajax and run into problems. I do my best to explain my problem as best I can.
I am working on a project in Laravel 8.
The user has the option to select a photo. CropperJS is used for this.
Everything works fine, as soon as I put the javascript and Ajax codes in a separate file, I get an error message (The POST method is not supported for this route. Supported methods: GET, HEAD, PATCH.)
How can I get ajax call working in a separate file?
routes
Route::get('/image/create', 'ProfileImage\CreateController#create')->name('image.create');
Route::post('/image/store', 'ProfileImage\StoreController#store')->name('image.store');
Controller
public function create()
{
return view('pages.image.create');
}
public function store(StoreProfileImageRequest $request, ProfileImage $profileImage)
{
$profileId = auth()->user()->profile->id;
$validated = $request->validated();
$image = $validated['image_name'];
$this->profileImageRepositoryInterface->storeImage($profileImage, $profileId, $image, $validated);
session()->flash('success', 'Uw afbeelding is succesvol opgeslagen.');
return response()->json(
[
'status' => 'success',
'message' => 'my message.',
'url' => route('profile.index')
]);
}
form
<form class="text-left"
data-form-output="form-output-global"
data-form-type="contact"
method="post"
enctype="multipart/form-data"
>
#csrf
<div class="member-block-body">
<label for="upload_image">
</label>
<input type="file" name="image_name" class="image" id="upload_image">
</div>
<span class="invalid-feedback ct_invalid_feedback" role="alert">
<strong id="ajax_image_error"></strong>
</span>
</form>
Modal
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalImageCropper" aria-hidden="true">
<div class="modal-dialog ct_modal_lg modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
#lang('Afbeelding aanpassen voordat u deze uploadt.')
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">
x
</span>
</button>
</div>
<div class="modal-body">
<div class="ct_img_container">
<div class="row">
<div class="col-md-8">
<img src="" id="sample_image" alt="">
</div>
<div class="col-md-4">
<div class="ct_cropper_image_preview"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" id="crop-image" class="btn btn-primary">
#lang('Opslaan')
</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">
#lang('Annuleren')
</button>
</div>
</div>
</div>
</div>
javascript
custom_function.js
$(document).ready(function () {
let $modal = $('#modal');
let image = document.getElementById('sample_image');
let cropper;
$('#upload_image').change(function (event) {
let files = event.target.files;
let done = function (url) {
image.src = url;
$modal.modal('show');
};
if (files && files.length > 0) {
reader = new FileReader();
reader.onload = function (event) {
done(reader.result);
};
reader.readAsDataURL(files[0]);
}
});
$modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 3,
preview: '.ct_cropper_image_preview'
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
$('#crop-image').click(function () {
$('#ajax_image_error').text('');
canvas = cropper.getCroppedCanvas({
width: 600,
height: 600
});
canvas.toBlob(function (blob) {
url = URL.createObjectURL(blob);
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
let base64data = reader.result;
$.ajax({
url: '{{ route("image.store") }}',
method: 'POST',
data: {
'_token': '{{ csrf_token() }}',
image_name: base64data
},
success: function (data) {
if (data.status === 'success') {
window.location = data.url;
$modal.modal('hide');
$("#image-preview").attr("src", base64data);
}
},
error: function (data) {
if (data.status === 422) {
let response = $.parseJSON(data.responseText);
$.each(response.errors, function (key, val) {
$("#" + "ajax_" + key + "_error").text(val[0]);
});
}
}
});
};
});
});
});
Thanx for your tips.
just solved the pronblem.
$.ajax({
url: '/image/store',
// url: '{{ route("image.store") }}',
method: 'POST',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: {
// '_token': '{{ csrf_token() }}',
image_name: base64data
},
success: function (data) {
if (data.status === 'success') {
window.location = data.url;
$modal.modal('hide');
$("#image-preview").attr("src", base64data);
}
},
error: function (data) {
if (data.status === 422) {
let response = $.parseJSON(data.responseText);
$.each(response.errors, function (key, val) {
$("#" + "ajax_" + key + "_error").text(val[0]);
});
}
}
});