Django Python can not upload directory with large quantity of files - ajax

I am trying to upload a directory with large number of dicom files using Django and JQuery ajax. Each file size is not more than 600kb. I can upload 200 files at a time. If I increase the number of files (tried to upload 14000 files), it doesn’t work. The site gets stuck and it’s not showing any error. Can anyone please help me with this problem? I have attached my code below. Thanks in advance.
View.py:
def handle_uploaded_file(f,filePath):
with open(filePath+'/'+f.name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
def UploadScanView(request):
if request.method == 'POST':
form = create_scan_form(request.POST)
if form.is_valid():
scan = form.save(commit=False)
scan.project_id = form.cleaned_data.get('project_id')
directory_name = request.POST.get('directories')
json_to_dictionary = json.loads(directory_name)
print(json_to_dictionary)
for upload_file in request.FILES.getlist('file'):
file_path = settings.MEDIA_ROOT+'/'+os.path.dirname(json_to_dictionary[upload_file.name])
print(file_path)
if os.path.exists(file_path):
handle_uploaded_file(upload_file, file_path)
else:
os.makedirs(file_path)
handle_uploaded_file(upload_file,file_path)
return render(request, 'fileupload/basic_upload/scan_upload.html', {'form': form})
else:
form = create_scan_form()
return render(request, 'fileupload/basic_upload/scan_upload.html', {'form': form})
HTML and JQuery:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
<script>
/*fileupload div*/
$(document).ready(function(){
$("#my-file").on('change',function(e){ //submit(function(e){
$("#file-wrap p").text('Now click on Upload button');
});
$("#my-form").on('submit',function(e){ //submit(function(e){
files = document.querySelector("#my-file").files;
var directories = {}
for (var file of files) {
file.webkitRelativePath
directories[file.name] = file.webkitRelativePath
}
directories = JSON.stringify(directories);
document.querySelector("#directories").value = directories
var eventType = $(this).attr("method"); // get method type for #my-form
var eventLink = $(this).attr("action"); // get action link for #my-form
//alert(directories);
//////
var formData = new FormData(this);
formData.append('csrfmiddlewaretoken', '{{ csrf_token }}');
$.ajax({
headers: { "X-CSRFToken": '{{ csrf_token }}' },
type: eventType,
url: eventLink,
//data: new FormData(this), // IMPORTANt
data: formData,
cache: false,
contentType: false,
processData: false,
// this part is progress bar
xhr: function () {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function (e) {
if (e.lengthComputable) {
var percentComplete = e.loaded / e.total;
percentComplete = parseInt(percentComplete * 100);
$('.myprogress').text(percentComplete + '%');
$('.myprogress').css('width', percentComplete + '%');
}
}, false);
return xhr;
},
success: function(getResult) {
$('#my-form')[0].reset(); // reset form
$("#file-wrap p").html('Drag and drop file here'); // change wrap message
}
});
e.preventDefault();
});
});
/*fileupload div*/
</script>
<form id="my-form" method="POST" action="{% url 'fileupload:upload_scan' %}" enctype="multipart/form-data"> <!--independentSub-->
{% csrf_token %}
<div id="user_form" class="container">
<div class="form-group col-sm-4" id="project_id">
{{ form.project_id|as_crispy_field }}
</div>
<!--fileupload div-->
<div id="independentSubDiv" class="row">
<div id="file-wrap" class="form-group col-sm-6" >
<p>Drag and drop file here</p>
<input id="my-file" type="file" name="file" multiple webkitdirectory directory draggable="true">
<input type="text" id="directories" name="directories" hidden />
</div>
</div>
<div style="padding-left: initial" id="independentSubDiv" class="form-group col-sm-7" >
<button type="submit" class="btn btn-primary btn-lg btn-block" name="submit_btn" id="submit_btn">Submit</button>
</div>
<div class="progress form-group col-sm-7" style="padding-left: initial" id="progressDiv" >
<div class="progress-bar progress-bar-success myprogress " role="progressbar">0%</div>
</div>
</div>
</form>

Related

Laravel How to handle file upload: Can't save image filename

So I want to upload a picture but it only store its description correctly. The file is stored as "noimage.jpg" which means the filename isn't read. I'm using modal btw. My database is named galleries and the migration contains these:
$table->id();
$table->timestamps();
$table->string('upload');
$table->longtext('description')->nullable();
CONTROLLER:
public function store(Request $request)
{
$galleries=new Gallery;
// Handle File Upload
if($request->hasFile('upload')){
// Get filename with the extension
$filenameWithExt = $request->file('upload')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('upload')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.$extension;
// Upload Image
$path = $request->upload('upload')->storeAs('public/upload', $fileNameToStore);
// make thumbnails
$thumbStore = 'thumb.'.$filename.'_'.time().'.'.$extension;
$thumb = Image::make($request->file('upload')->getRealPath());
$thumb->save('storage/upload/'.$thumbStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
$galleries->description = $request->input('description');
$galleries->upload = $fileNameToStore;
$galleries->save();
}
FORM:
<form id="uploadForm">
<div class="modal-body">
<input type="hidden" name="id" id="id">
<!-- Upload image input-->
<div class="input-group mb-3 px-2 py-2 rounded-pill bg-secondary shadow-sm">
<input type="file" name="upload" id="upload" onchange="readURL(this);" class="form-control border-0">
<label id="upload-label" for="upload" class="font-weight-light text-muted">Choose file</label>
<div class="input-group-append">
<label for="upload" class="btn btn-light m-0 rounded-pill px-4"> <i class="fa fa-cloud-upload mr-2 text-muted"></i><small class="text-uppercase font-weight-bold text-muted">Choose file</small></label>
</div>
</div>
<!-- Uploaded image area-->
<p class="font-italic text-white text-center">The image uploaded will be rendered inside the box below.</p>
<div class="image-area mt-4 bg-white"><img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"></div>
<label>Caption</label>
<input type="textarea" class="form-control text-white" name="description" id="description">
</div>
</form>
AJAX
<script>
$(document).ready(function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
//ADD PICTURE
$('#btnUpload').click(function(){
$('#uploadModal').modal('show');
});
$('#btnSave').click(function(){
$.ajax({
data: $('#uploadForm').serialize(),
url: "{{ route('home.store') }}",
type: "POST",
dataType: 'json',
success: function(data){
$('#uploadModal').modal('hide');
},
error: function(data){
console.log('Error:', data);
}
});
});
//Image reader to show pic when selected
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#imageResult')
.attr('src', e.target.result);
};
reader.readAsDataURL(input.files[0]);
}
}
$(function () {
$('#upload').on('change', function () {
readURL(input);
});
});
var input = document.getElementById( 'upload' );
var infoArea = document.getElementById( 'upload-label' );
input.addEventListener( 'change', showFileName );
function showFileName( event ) {
var input = event.srcElement;
var fileName = input.files[0].name;
infoArea.textContent = 'File name: ' + fileName;
}
});
</script>
Assuming you're using ajax to upload the file, you'll need to use a FormData object instead of .serialize()
$.ajax({
data: new FormData($('#uploadForm').get(0)), // use formdata object
url: "{{ route('home.store') }}",
type: "POST",
dataType: 'json',
contentType: false, // required for
processData: false, // jquery ajax file upload
success: function(data){
$('#uploadModal').modal('hide');
},
error: function(data){
console.log('Error:', data);
}
});
You don't add "enctype" in form tag.
Change your code:
<form id="uploadForm">
with:
<form id="uploadForm" enctype='multipart/form-data'>
If this above not working then:
1.install this package by following command:
composer require "laravelcollective/html":"^5.2.0"
2.In config/app add this line:
'providers' => [
// ...
**Collective\Html\HtmlServiceProvider::class,**
// ...
],
and
'aliases' => [
// ...
**'Form' => Collective\Html\FormFacade::class,
'Html' => Collective\Html\HtmlFacade::class,**
// ...
],
3.Change Form:
{!! Form::open([ 'action'=> 'NameofController#store', 'method' => 'POST','enctype' => 'multipart/form-data' ]) !!}
<div class="form-group">
{{Form::text('name','' , ['class' =>'form-control'])}}
</div>
<div class="form-group">
{{Form::text('phone','' , ['class' =>'form-control', 'placeholder' => 'phone' ])}}
</div>
<div class="form-group">
{{Form::file('image_name')}}
</div>
{{Form::submit('Submit' , ['class' =>'btn btn-primary' ])}}
{!! Form::close() !!}
you can this way to store your file with custom name:
$path = $request->file('upload')->store('public/upload/' .$fileNameToStore);

How to update data on a page using ajax script?

There is a script that needs to update the data on the page in a specific div. But instead of updating, the block with the div is simply hidden and in order for it to appear again, you need to reload the page. The data comes in data, but here is $ ("# userPost" + id) .html (data); something doesn't work.
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('.infinite-scroll').on('click', '#editPostButton', function(e) {
e.preventDefault();
var id = $(this).data('id');
var user_id = $('#userForm').val();
var form = document.getElementById('EditPostForm'+id);
var formData = new FormData(form);
// var formData = $('#EditPostForm'+id).serialize();
$.ajax({
url: "id"+user_id+"/"+id+"/edit",
type: "POST",
data: formData,
success: function(data) {
console.log(data);
$("#userPost"+id).html(data);
$("#closeButton"+id).click();
},
error: function() {
console.log('error');
},
processData: false,
contentType: false,
});
});
And div
<div id="userPost{{$post->id}}">
#if($post->img)
<div>
<img src="{{$post->img}}" class="img-fluid">
</div>
#endif
<br>
#if($post->title)
<div class=" mr-1 mb-3 titleleft">
<h5 style="color: black"><b>{{$post->title}}</b></h5>
</div>
#endif
#if($post->message)
<div class="text-muted text-small margins" style="white-space: pre-wrap;">{{mb_strimwidth($post->message, 0, 600, " . . . Read more")}}</div>
#endif
#if($post->videoPost)
<div class="embed-responsive embed-responsive-16by9 mt-4 mb-2">
<iframe class="embed-responsive-item" src="{{$post->videoPost}}" allowfullscreen></iframe>
</div>
#endif
</div>
Try doing this way:
$("#userPost"+id).load(url);
or
$("#userPost"+id).html(data).load(url);

Using Ajax and Django conditions to display an html variable

I'm new to using Ajax calls with Django. Im trying to implement a simple Display or not display depending on the type of get called by Ajax:
Views:
def dynamic(request):
context = {}
if request.method == 'GET':
if 'backtest_type' in request.GET:
context['display_details'] = False
print ('Im not displaying')
elif 'change_val' in request.GET:
context['display_details'] = True
print ('Im displaying')
else:
context['display_details'] = False
return render(request, "demo/dynamic.html", context)
In my template:
{% extends 'demo/base.html' %}
{% block body %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'css/dynamic.css' %}">
<script>
$(document).on('click','#id_backtest_type', function () {
console.log( $(this).val() );
$.ajax({
type: 'get',
data: {'backtest_type': 1},
success: function (data) {
console.log('data sent ' + data);
},
failure: function(data) {
alert('Got an error dude');
}
});
});
$(document).on('click','#btnClick', function () {
// console.log( $(this).val() );
$.ajax({
type: 'get',
data: {'change_val': 1},
success: function (data) {
console.log('data sent ' + data);
failure: function(data) {
alert('Got an error dude');
}
});
});
</script>
<div>
{% if display_details %}
<h1>I'm diplaying</h1>
{% endif %}
</div>
<div id="btnClick" class="col-sm-4">
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group">
<button class="btn btn-secondary" type="button">Don't Display</button>
</div>
</div>
</div>
<div id="id_backtest_type" class="col-sm-4">
<div class="btn-group btn-group-justified" role="group">
<div class="btn-group" role="group">
<button class="btn btn-secondary" type="button">Display!</button>
</div>
</div>
</div>
{% endblock %}
From the console I'm sure that the get requests are being correctly sent using ajax (the get requests are being sent and the console prints the statements:
[09/Feb/2019 20:00:56] "GET /dynamic/?backtest_type=1 HTTP/1.1" 200
6530
Im displaying
However, even if the ajax call works correctly, the template doesn't end up rendering <h1>I'm diplaying</h1>. Am I misunderstanding anything about Ajax?
Thanks in advance!

Laravel: Dropzone js, getting [object Object], but why?

I'm trying to upload an image using Dropzone.js in Laravel, but I'm getting an error showing [object Object] on my thumbnails after uploading a photo. I can't find my error and I don't understand what the cause is.
Here is my code and an image of the error. Why is this happening? What can I do?
View:
<div class="container col-md-8 col-12 mx-auto">
<div class="row">
<div class="col-sm-10 offset-sm-1">
<h2 class="page-heading">Upload your Images <span id="counter"></span></h2>
<form method="post" action="{{ url('/addimage') }}"
enctype="multipart/form-data" class="dropzone" id="my-dropzone">
{{ csrf_field() }}
<div class="dz-message">
<div class="col-xs-8">
<div class="message">
<p>Drop files here or Click to Upload</p>
</div>
</div>
</div>
<div class="fallback">
<input type="file" name="file" multiple>
<input type="hidden" name="id" value="{{$id}}" >
</div>
</form>
</div>
</div>
</div>
Route:
Route::group(['middleware'=>'auth'], function (){
...
Route::post('/addimage', 'FrontendController#addimage');
Route::post('/adddeleteimage', 'FrontendController#adddeleteimage');
...
});
Controller:
public function addimage(Request $request){
$file = $request->file('file');
$filename = uniqid().".".$file->clientExtension();
$file->move('img/product', $filename);
$dropzone = new Imagedb;
$dropzone->product_id = $request->id;
$dropzone->url = 'img/product'.$filename;
$dropzone->save();
}
JS:
var total_photos_counter = 0;
Dropzone.options.myDropzone = {
uploadMultiple: true,
parallelUploads: 2,
maxFilesize: 16,
acceptedFiles: "image/*",
resizeWidth: 360,
previewTemplate: document.querySelector('#preview').innerHTML,
addRemoveLinks: true,
dictRemoveFile: 'Remove file',
dictFileTooBig: 'Image is larger than 16MB',
timeout: 10000,
init: function () {
this.on("removedfile", function (file) {
$.post({
url: '/adddeleteimage',
data: {id: file.name, _token: $('[name="_token"]').val()},
dataType: 'json',
success: function (data) {
total_photos_counter--;
$("#counter").text("# " + total_photos_counter);
}
});
});
},
success: function (file, done) {
total_photos_counter++;
$("#counter").text("# " + total_photos_counter);
}
};
Firstly, try
$('meta[name="csrf-token"]').attr('content')
as token
I fixed this error by adding in head tag
<meta name="csrf-token" content="{{ csrf_token() }}">
and in dropzone initialization config
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
Example:
autoProcessQueue:false,
required:true,
acceptedFiles: ".png,.jpg,.gif,.bmp,.jpeg",
addRemoveLinks: true,
maxFiles:8,
parallelUploads : 100,
maxFilesize:5,
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }

Vuejs Cannot Submit Form Ajax

I want to submit data via modal Semantic UI and Vuejs. But my form cannot submit data via Ajax. i'm tired to find the problem, maybe someone can help me.
My View like this.
<form v-on:submit.prevent="addProductCategory" class="ui form">
<div class="content">
<div class="description">
<div class="field" v-bind:class="{'has-error': input.errorsAddProductCategory.name}">
<label for="name">Name</label>
<input v-model="input.addProductCategory.name" type="text" id="name" name="name">
<div class="help-block" v-if="input.errorsAddProductCategory.name"
v-text="input.errorsAddProductCategory.name[0]"></div>
</div>
</div>
</div>
<div class="actions">
<div class="ui black deny button">
No
</div>
<button type="submit" class="ui positive right button">Add</button>
</div>
</form>
<script type="text/javascript">
const CSRF_TOKEN = '{{ csrf_token() }}';
const URLS = {
productCategory: {
addProductCategory: '{{ route('product-category.store') }}',
}
};
</script>
Function to Add Data.
function addProductCategory() {
var data = app.input.addProductCategory;
data._token = CSRF_TOKEN;
$.ajax({
url: URLS.productCategory.addProductCategory,
method: 'POST',
data: data,
success: function (data) {
app.input.addProductCategory = {
name: ""
};
app.input.errorsAddProductCategory = [];
$('#modal-create').modal('hide');
}
error: function (data) {
if (data.status === 401) { // unauthorized
window.location.reload();
} else if (data.status === 422) {
app.input.errorsAddProductCategory = data.responseJSON;
} else {
alert('There is an error.');
console.log(data);
}
}
});
}
And Vuejs
var app = new Vue({
el: "#app",
data: function () {
return {
input: {
addProductCategory: {
name: ""
},
errorsAddProductCategory: [],
editProductCategory: {
name: ""
},
errorsEditProductCategory: []
}
};
},
methods: {
addProductCategory: addProductCategory,
}
});

Resources