Dropzone only builds thumbnail for last file - php

i need to preload existing files into an instance of a Dropzone-Div. I looked up some similar issues on the net, but couldn't find something. I want to create Thumbnails on the go and it works great as Long as there is only one file. If there is more then 1 file it only generates the thumbnail for the last one.
This is the init-function from my .dropzone:
init: function() {
// Create the mock files:
var dropZoneInstance = this;
// Load Files
$.ajax({
url: 'ajaxcall.php',
data: {id: profil,zuordnung: zuordnung, ajaxcall: 'readAnhänge'},
success: function (response) {
var files = JSON.parse(response);
for (i = 0; i < files.length; i++)
{
var obj = files[i];
console.log(obj);
dropZoneInstance.files.push(obj);
dropZoneInstance.emit("addedfile", obj);
dropZoneInstance.createThumbnailFromUrl(obj,
dropZoneInstance.options.thumbnailWidth,
dropZoneInstance.options.thumbnailHeight,
dropZoneInstance.options.thumbnailMethod, true, function (thumbnail)
{
dropZoneInstance.emit('thumbnail', obj, thumbnail);
}
);
dropZoneInstance.emit("complete", obj);
}
}
});
}
This is the PHP-Code for the JSON:
function ReadFromZuordnung($zuordnung = 0)
{
$var = Array();
global $dbh;
global $user;
$query = $dbh->prepare("
SELECT
anhang_id AS id
FROM
tbl_anhang
WHERE
anhang_profil = :profil
AND
anhang_zuordnung = :zuordnung
");
$query->bindValue(':profil', $this->getId(), PDO::PARAM_INT);
$query->bindValue(':zuordnung', $zuordnung, PDO::PARAM_INT);
$query->setFetchMode(PDO::FETCH_CLASS, 'Test');
$query->execute();
while($row = $query->fetch())
{
$var[] = Array("id"=>$row->getId(),"name"=>$row->getName(),"size"=>0,"dataURL"=>$this->getUploadPfad().$row->getName());
}
echo json_encode($var);
}
And thats my test.php:
<div id="dropzone" class="dropzone" profil="1">
<div class="dz-default dz-message"></div>
</div>
That's the result: https://imgur.com/9ezsnrk
I want to have thumbnails for every file, not just the last one.
Any Suggestions?

Ok, i got it myself after two more days of searching for answerts:
Just changing
var obj = files[i];
to
let obj = files[i];
solved the Problem.
Maybe someone else will save some time when he is having the same Problem.

Related

zip multiple files on server and echo back zip file

Consider a site which allows user to store files (pdf, docx, jpeg, png, gif only). Part of the html:
<ul>
<li>lola.doc</li>
<li>lola.pdf</li>
<li>lola.jpeg</li>
<li>lola.docx</li>
</ul>
When a user clicks on any of the above, the file either opens or a save dialpg appears. This is fine.
Now I want user to be able to select some of these files (which are on the server). The files will be zipped and echo back to user with a prompt to save. I cannot use above, so I have this option:
html:
<select class="multiple_select " multiple>
<option value="../folder/lola.doc">lola.doc</option>
<option value="../folder/lola.pdf">lola.pdf</option>
<option value="../folder/lola.jpeg">lola.jpeg</option>
<option value="../folder/lola.docx">lola.docx</option>
</select>
<button id="btn" type="button">Download</button>
js:
js:
$('#btn').on('click', function() {
var options_selected = $('select').find('option:selected');
options_selected_le = options_selected.length;
var i;
var options_selected_arr = [];
var options_names_arr = [];
for (i=0; i<options_selected_le; i++) {
options_selected_arr.push(options_selected.eq(i).val());
options_names_arr.push(options_selected.eq(i).text());
}
var fd = new FormData();
fd.append('zipname', zipname);
fd.append('options_selected_arr', JSON.stringify(options_selected_arr));
fd.append('options_names_arr', JSON.stringify(options_names_arr));
$.ajax({
url: 'download_multiple_files.php',
type: 'post',
data: fd,
cache: false,
contentType: false,
processData: false,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-Download", "yes");
},
success: function(response){
alert(response); //I am sure this is wrong
// Do I need js to handle zip file here. I guess php should automatically do this
}
});
});
<?php
session_start();
require 'server_conn.php'; // for connection and holds test_input function
// do some security checks ...
$zipname = 'file.zip';
$arr = json_decode($_POST['options_selected_arr']);
$file_arr = [];
foreach ($arr as $obj) {
array_push($files_arr, test_input($obj));
}
$arr = json_decode($_POST['options_names_arr']);
$files_names_arr = [];
foreach ($arr as $obj) {
array_push($files_names_arr, test_input($obj));
}
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
for ($i=0; $i<$c; $i++) {
$zip->addFile($file_arr[$i], $files_names_arr[$i]);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($zipname));
header('Content-Disposition: attachment; filename="file.zip"');
readfile($zipname);
unlink($zipname);
?>
Response from server is giberish and there is no error indication. I suspect my php is defective.
I have solved this using 2 methods:
Method 1:
JSZip without php (Each select option already contains file path as value)
The advantage of this method: It does not store the new zip file on the server, so storage is not a problem.
I believe using blob will also allow ziping large files, max size I don't know.
To use this method, one needs to download Filesaver, jszip and jszip utility and add following lines to the html doc body
<script src="../js/lib/jszip.min.js"></script>
<script src="../js/lib/jszip-utils.min.js"></script>
<script src="../js/lib/FileSaver.js"></script>
The js script makes use of Promisejs, which I haven't studied before (but will now do). Below is the js:
$('#btn').on('click', function() {
function urlToPromise(url) {
return new Promise(function(resolve, reject) {
JSZipUtils.getBinaryContent(url, function (err, data) {
if(err) {
reject(err);
} else {
resolve(data);
}
});
});
}
var options_selected = $('select').find('option:selected');
options_selected_le = options_selected.length;
var zipname = 'file.zip';
var Promise = window.Promise;
if (!Promise) {
Promise = JSZip.external.Promise;
}
var i;
var zip = new JSZip();
for (i=0; i<options_selected_le; i++) {
var url = options_selected.eq(i).val();
var filename = options_selected.eq(i).text();
zip.file(filename, urlToPromise(url), {binary:true});
}
zip.generateAsync({type:"blob"}).then(function callback(blob) {
//see FileSaver.js
saveAs(blob, zipname);
//alert('success');
}, function (e) {
alert('Error zipping file(s). Retry');
});
});
Method 2:
Using js and PHP:
First create a folder on the server to hold the zip file, I name the folder 'archive'
This is why I may not vote for this method.
New js:
$('#btn').on('click', function() {
var options_selected = $('select').find('option:selected');
options_selected_le = options_selected.length;
var zipname = 'file.zip';
var fd = new FormData();
fd.append('zipname', zipname);
fd.append('options_selected_arr', JSON.stringify(options_selected_arr));
fd.append('options_names_arr', JSON.stringify(options_names_arr));
$.ajax ({
url: 'download_multiple_files.php',
type: 'post',
data: fd,
cache: false,
contentType: false,
processData: false,
success: function(response){
window.location = response;
}
});
});
New php:
<?php
session_start();
// connect to server, scan input data and do some security checks ...
$zipname = 'file.zip';
$arr = json_decode($_POST['options_selected_arr']);
$file_arr = [];
foreach ($arr as $obj) {
array_push($files_arr, test_input($obj));
}
$arr = json_decode($_POST['options_names_arr']);
$files_names_arr = [];
foreach ($arr as $obj) {
array_push($files_names_arr, test_input($obj));
}
$zip = new ZipArchive();
$path = '/archive/'.$zipname;
if ($zip->open($path, ZipArchive::CREATE)!==TRUE) {
echo 'Cannot zip files'; die;
}
$c = count($file_arr);
for ($i=0; $i<$c; $i++) {
$zip->addFile($file_arr[$i], $files_names_arr[$i]);
}
$zip->close();
echo $path;
mysqli_close($conn);
?>
This will force save dialog to appear. Two pending challenges I have for this method are:
Prevent a new window to open
The save dialog appears with download as file name but without extension .zip. So user should type .zip along with the name. I would prefer the computed zip filename to appear in the save dialog

Ajax - variables are seen in chrome network tab but they don't seem to pass to the PHP function

I am trying to update a php function using ajax.
I Have an array stored in localstorage.
The array contains values of clicked id's.
When I click the <tr>, the array gets updated and sent via ajax from a js file to the php file.
js file
function storeId(id) {
var ids = JSON.parse(localStorage.getItem('reportArray')) || [];
if (ids.indexOf(id) === -1) {
ids.push(id);
localStorage.setItem('reportArray', JSON.stringify(ids));
}else{
//remove id from array
var index = ids.indexOf(id);
if (index > -1) {
ids.splice(index, 1);
}
localStorage.setItem('reportArray', JSON.stringify(ids));
}
return id;
}
//ajax function
$('table tr').click(function(){
var id = $(this).attr('id');
storeId(id);
var selected_lp = localStorage.getItem('reportArray');
console.log(selected_lp);
var query = 'selected_lp=' + selected_lp;
$.ajax({
type: "POST",
url: "../inc/updatelponadvdash.php",
data: { selected_lparr : selected_lp},
cache: false,
success: function(data) {
return true;
}
});
});
updatelponadvdash.php file
<?php
require_once 'inc.php';
$selected_lparr = json_decode($_POST['selected_lparr']);
foreach($selected_lparr as $value){
$dbData = $lploop->adv_lploops($value);
}
?>
Now, in the chrome network tab, when I click the and I dump_var($selected_lparr) the array is updated and I see the values like this:
For some reason I get a 500 error.
As well I dont understand why the var_dump(inside the function below) dosent work. I seems that the function adv_lploops dosent get the variables. but i dont understand why.
This is the fuction I call:
public function adv_lploops($value){
$sql = "SELECT * FROM `lptitels` WHERE titleidNo = '$value'";
$row = $sql->fetch(PDO::FETCH_ASSOC);
var_dump($row);
}
You aren't executing the sql query, try the following:
$sth = $db->prepare($sql);
$sth->execute();
$row = $sth->fetch(PDO::FETCH_ASSOC);
note: you will need the $db object which is a connection to your database

Trying to populate worker ID using Compay Name but only the first worker in that company is displayed in dropdown

This is the view page code in code Igniter.
I am able to populated the second drop down(worker Id) but the problem is, only first data is being fetched. As it has more than 50 worker, only 1 worker id is being fetched.
$(document).ready(function() {
$('#name_of').change(function() {
var Worker_id = $('#name_of').val();
$.ajax({
type:'POST',
data:{data:Worker_id},
dataType:'text',
url:"<?php echo base_url(); ?>supply_chain/get_filtered_names_for_time_card",
success:function(result) {
result = JSON.parse(result);
$('#Worker').empty();
for(i in result) {
$('#Worker').append("<option value='"+result[i]['Worker_id']+"'>"+result[i]['Worker_id']+" "+result[i]['Worker_name']+"</option>")
}
}
});
});
});
This is the Controller function for above View through which I am trying to get all workers related to that required company name.
public function get_filtered_names_for_time_card() {
$id = $this->input->post('data');
$companyName = $this->supply_model->get_all_names_for_time_card();
for($i = 0;$i < sizeof($companyName);$i++){
if($companyName[$i]['company_name'] == $id){
$data['companyNameOptions'] = [$companyName[$i]];
break;
}
}
echo json_encode($data['companyNameOptions']);
}
It would be a much better idea to make the query select only the row you want but your problem with the code you have written is you over writing the data each time round your loop
Also once you find a company_name you want you terminate the for loop with a break so you will only ever add one to the resulting $data array
public function get_filtered_names_for_time_card()
{
$id = $this->input->post('data');
$companyName = $this->supply_model->get_all_names_for_time_card();
for($i = 0;$i < sizeof($companyName);$i++){
if($companyName[$i]['company_name'] == $id){
$data['companyNameOptions'][] = $companyName[$i];
// note here ^^
//break;
}
}
echo json_encode($data['companyNameOptions']);
}
Also the $data array does not need to have a sub array so above code can be written more simply and clearly as
public function get_filtered_names_for_time_card()
{
$id = $this->input->post('data');
$companyName = $this->supply_model->get_all_names_for_time_card();
for($i = 0;$i < sizeof($companyName);$i++){
if($companyName[$i]['company_name'] == $id){
$data[] = $companyName[$i];
}
}
echo json_encode($data);
}
And in your javascript, if you are returning JSON then tell the ajax call that you are doing that and you can forget about the JSON.parse()
$(document).ready(function(){
$('#name_of').change(function(){
var Worker_id = $('#name_of').val();
$.ajax({
type:'POST',
data:{data:Worker_id},
//dataType:'text',
dataType:'json',
url:"<?php echo base_url(); ?>supply_chain/get_filtered_names_for_time_card",
success:function(result)
{
//result = JSON.parse(result);
$('#Worker').empty();
for(i in result){
$('#Worker').append("<option value='"+result[i]['Worker_id']+"'>"+result[i]['Worker_id']+" "+result[i]['Worker_name']+"</option>")
}
}
});
});
});

upload image and store into my folder using jquery and php the below code procedure [duplicate]

Admittedly, there are similar questions lying around on Stack Overflow, but it seems none quite meet my requirements.
Here is what I'm looking to do:
Upload an entire form of data, one piece of which is a single file
Work with Codeigniter's file upload library
Up until here, all is well. The data gets in my database as I need it. But I'd also like to submit my form via an AJAX post:
Using the native HTML5 File API, not flash or an iframe solution
Preferably interfacing with the low-level .ajax() jQuery method
I think I could imagine how to do this by auto-uploading the file when the field's value changes using pure javascript, but I'd rather do it all in one fell swoop on for submit in jQuery. I'm thinking it's not possible to do via query strings as I need to pass the entire file object, but I'm a little lost on what to do at this point.
Can this be achieved?
It's not too hard. Firstly, take a look at FileReader Interface.
So, when the form is submitted, catch the submission process and
var file = document.getElementById('fileBox').files[0]; //Files[0] = 1st file
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
reader.onload = shipOff;
//reader.onloadstart = ...
//reader.onprogress = ... <-- Allows you to update a progress bar.
//reader.onabort = ...
//reader.onerror = ...
//reader.onloadend = ...
function shipOff(event) {
var result = event.target.result;
var fileName = document.getElementById('fileBox').files[0].name; //Should be 'picture.jpg'
$.post('/myscript.php', { data: result, name: fileName }, continueSubmission);
}
Then, on the server side (i.e. myscript.php):
$data = $_POST['data'];
$fileName = $_POST['name'];
$serverFile = time().$fileName;
$fp = fopen('/uploads/'.$serverFile,'w'); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $serverFile );
echo json_encode($returnData);
Or something like it. I may be mistaken (and if I am, please, correct me), but this should store the file as something like 1287916771myPicture.jpg in /uploads/ on your server, and respond with a JSON variable (to a continueSubmission() function) containing the fileName on the server.
Check out fwrite() and jQuery.post().
On the above page it details how to use readAsBinaryString(), readAsDataUrl(), and readAsArrayBuffer() for your other needs (e.g. images, videos, etc).
With jQuery (and without FormData API) you can use something like this:
function readFile(file){
var loader = new FileReader();
var def = $.Deferred(), promise = def.promise();
//--- provide classic deferred interface
loader.onload = function (e) { def.resolve(e.target.result); };
loader.onprogress = loader.onloadstart = function (e) { def.notify(e); };
loader.onerror = loader.onabort = function (e) { def.reject(e); };
promise.abort = function () { return loader.abort.apply(loader, arguments); };
loader.readAsBinaryString(file);
return promise;
}
function upload(url, data){
var def = $.Deferred(), promise = def.promise();
var mul = buildMultipart(data);
var req = $.ajax({
url: url,
data: mul.data,
processData: false,
type: "post",
async: true,
contentType: "multipart/form-data; boundary="+mul.bound,
xhr: function() {
var xhr = jQuery.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(event) {
var percent = 0;
var position = event.loaded || event.position; /*event.position is deprecated*/
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
def.notify(percent);
}
}, false);
}
return xhr;
}
});
req.done(function(){ def.resolve.apply(def, arguments); })
.fail(function(){ def.reject.apply(def, arguments); });
promise.abort = function(){ return req.abort.apply(req, arguments); }
return promise;
}
var buildMultipart = function(data){
var key, crunks = [], bound = false;
while (!bound) {
bound = $.md5 ? $.md5(new Date().valueOf()) : (new Date().valueOf());
for (key in data) if (~data[key].indexOf(bound)) { bound = false; continue; }
}
for (var key = 0, l = data.length; key < l; key++){
if (typeof(data[key].value) !== "string") {
crunks.push("--"+bound+"\r\n"+
"Content-Disposition: form-data; name=\""+data[key].name+"\"; filename=\""+data[key].value[1]+"\"\r\n"+
"Content-Type: application/octet-stream\r\n"+
"Content-Transfer-Encoding: binary\r\n\r\n"+
data[key].value[0]);
}else{
crunks.push("--"+bound+"\r\n"+
"Content-Disposition: form-data; name=\""+data[key].name+"\"\r\n\r\n"+
data[key].value);
}
}
return {
bound: bound,
data: crunks.join("\r\n")+"\r\n--"+bound+"--"
};
};
//----------
//---------- On submit form:
var form = $("form");
var $file = form.find("#file");
readFile($file[0].files[0]).done(function(fileData){
var formData = form.find(":input:not('#file')").serializeArray();
formData.file = [fileData, $file[0].files[0].name];
upload(form.attr("action"), formData).done(function(){ alert("successfully uploaded!"); });
});
With FormData API you just have to add all fields of your form to FormData object and send it via $.ajax({ url: url, data: formData, processData: false, contentType: false, type:"POST"})

Success handling behavior in Ext.Ajax.request

I am working on extjs 4 project. In this project I have to communicate back and fourth between js and php files. So to call php from js, I am using Ext.Ajax.request.
var dirs = [];
Ext.Ajax.request(
{
url: 'text.php',
method: 'GET',
success: function(response)
{
dirs = JSON.parse(response.responseText);
},
failure: function(response)
{
alert('server-side failure with status code ' + response.status);
}
});
// Creating dropdown list menu
document.write("<select class='select'>");
for (var i = 0; i < dirs.length; i++)
{
document.write("<option>" + dirs[i] + "</option>");
}
document.write("</select>");
php code is the following:
<?php
$filepath = "scenarios";
$dirs = array();
$files = array();
$scenes = array_diff(scandir($filepath), array('..', '.'));
for ($i = 2; $i < count($scenes)+2; $i++)
{
if (strpos($scenes[$i], '.'))
{
array_push($files, $scenes[$i]);
}
else
{
array_push($dirs, $scenes[$i]);
}
}
if (count($dirs) > 0)
{
echo json_encode($dirs);
}
else
{
echo json_encode("You do nat have any projects. Please create new project.");
}
?>
Now the problem appears in the part where I want to generate list menu from the resulting dirs object. In the firebug DOM dirs = ["google","yahoo"], but in the loop, dirs.length returns 0???
Also when I put alert(dirs.length) before the for loop, it shows 0, then correctly generates the list menu...weird????
The request call is asynchronous which means, that after calling Ext.Ajax.Request, the next instruction is your loop. But you haven't received the data from the server yet. You need to put the loop in the success callback to make sure that you'll execute it after getting the data from the server.
var dirs = [];
Ext.Ajax.request(
{
url: 'text.php',
method: 'GET',
success: function(response)
{
dirs = JSON.parse(response.responseText);
// Creating dropdown list menu
document.write("<select class='select'>");
for (var i = 0; i < dirs.length; i++)
{
document.write("<option>" + dirs[i] + "</option>");
}
document.write("</select>");
},
failure: function(response)
{
alert('server-side failure with status code ' + response.status);
}
});
Also when I put alert(dirs.length) before the for loop, it shows 0,
then correctly generates the list menu...weird????
This is because the alert stop the execution flow of your program until you click on "ok". The data are probably coming from the server during this time, and the dir variable is populated with them.
I can't see any headers being sent out - which is required by most browsers:
header('content-type: application/json; charset=utf8;');
if(sizeof($dirs) > 0){
echo json_encode(array('success' => true, 'data' => $dirs));
}
else {
echo json_encode(array('success' => false, 'error' => 'You do not have any projects.' ));
}
The JavaScript:
var xhr = new Ext.data.Connection();
xhr.request({
url: '/text.php',
method: 'GET',
headers: {'Accept':'application/json'},
success: function(response, opts) {
var obj=Ext.decode(response.responseText);
var html='';
Ext.each(obj.data, function(v,i){html+='<option>'+v+'</option>';});
html='<select>'+html+'</select>';
console.info(html);
}
});
The HTML generation has to reside in the callback function - else it makes no sense at all.
Without having seen the JSON which is being returned - it's hard to tell what's wrong with it.
Down-voting without leaving a comment why exactly is really lame.

Categories