How can I avoid <input file> deletes values after selecting files? - php

I'm working on a web uploader, however, I found something, I do not know if it's a problem. This is what I found:
When I choose files with <input type="file" multiple>, the values ​​of all selected files are stored in a list of files which is within the INPUT. However, when I add more files, the files that I select replace those I selected previously. I think this is a default behavior of this element DOM.
What do I have to do if I want to add more files without deleting my chosen before?
Does anyone know how to do this?
Btw: Sorry for my bad english, It's not my mother language.Thanks.

You can keep track of all FileLists, and loop over each one when sending through ajax: http://jsfiddle.net/46Pk8/. However, keep in mind that you can select (and upload) a file more than once this way. A better method would be to have a visual list, and let the user be able to add/remove files to/from the list.
var files = []; // this will contain FileLists
$("button:first").on("click", function(e) {
$("<input>").prop({
"type": "file",
"multiple": true
}).on("change", function(e) {
files.push(this.files);
}).trigger("click");
});
$("button:last").on("click", function(e) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "/echo/html/", true);
var data = new FormData();
$.each(files, function() { // each FileList
$.each(this, function() { // each file inside this list
console.log("appending %s", this.name);
data.append("files", this);
});
});
xhr.onreadystatechange = function(e) {
if(xhr.readyState === 4) {
console.log("done");
}
};
xhr.send(data);
});

As workaround you can insert another input after file choose and hide original one.

Related

jQuery only upload last dragged files

I followed this tutorial on how to create a DragNDrop file upload.
It basically consists of
<form id='dragform'>
<input type="file" name="file[]" id="fileC" class="inputfile" multiple />
<label for="fileC" id='dropLabel'>
</label>
</form>
where the input is hidden.
The upload is done by
var $form = $('#dragform');
.on('drop', function(e)
{
droppedFiles = e.originalEvent.dataTransfer.files;
$form.trigger('submit');
});
var $input = $('.inputfile');
$input.on( 'change', function( e )
{
$form.trigger('submit');
});
$form.on('submit', function(e)
{
var ajaxData = new FormData($form.get(0));
if (droppedFiles) {
$.each( droppedFiles, function(i, file) {
ajaxData.append( $input.attr('name'), file );
});
}
[...]
});
This means there are 2 options to upload files, either by selecting or by dropping. In both cases the files are directly uploaded with AJAX. Here comes now my problem:
If I select file1.pdf then ajaxData only contains file1.pdf. If I now drop file2.pdf and file3.pdf in the DragNDrop area, then ajaxData contains file1.pdf, file2.pdf and file3.pdf - but I only want it to contain the dragged files file2.pdf and file3.pdf, since file1.pdf has been uploaded before. If I now select file4.pdf, then ajaxData includes file2.pdf,file3.pdf and file4.pdf.
What do I need to change, so that I only get the last dragged or last selected files from my form?
This works now:
var ajaxData;
if (droppedFiles) {
ajaxData = new FormData();
$.each( droppedFiles, function(i, file) {
ajaxData.append( $input.attr('name'), file );
});
}
else {
ajaxData = new FormData($form.get(0));
}
droppedFiles = "";

How to download a pdf using ajax and TCPDF

My code works fine when I run the php script without ajax as a GET request. I get prompted to download the rendered pdf and all is well. However, I need to use ajax because I need to send more info from an html page to the php script than can be handled in a GET request.
What do I need to put into my ajax to make this work?
Thanks
js
function makePDF()
{
var x;
if(window.event) // IE8 and earlier
{
x=event.keyCode;
}
else if(event.which) // IE9/Firefox/Chrome/Opera/Safari
{
x=event.which;
}
keychar=String.fromCharCode(x);
alert(keychar);
if (keychar == 'p' || keychar == 'P')
{
var charSheetHTML = characterSheet.innerHTML;
$.ajax({
url: 'pdf.php',
data: {'charactersheet': charSheetHTML,},
type: 'post',
success: function (data) {**WHAT_DO_I_PUT_HERE??**},
error: function (data) { alert("error\n" + data.toString()); }
});
}
}
pdf.php
<?php
include_once( "bxcharacter/PDFChar.php.inc" );
PDFChar();
?>
PDFChar.hph.inc
<?php
require_once('./tcpdf/tcpdf.php');
function PDFChar(){
$pdf = new TCPDF();
$pdf->AddPage('P');
$pdf->writeHTML($_POST['charactersheet']);
$pdf->Output("character.pdf", 'D');
}
?>
This is not an ajax solution, but you can send your data with this way and if no error occurs, your page will not change.
Create a form element with inputs hidden which contains your data you want to send:
example format:
<form id="myForm" method="GET" action="pdf.php">
<input type="hidden" name="data1" type="hidden" value="your JSON.stringify() data">
</form>
js code (call these where your ajax request is):
var myForm = '<form id="myForm" method="GET" action="pdf.php">';
myForm += '<input type="hidden" name="data1" type="hidden" value="JSON.stringify() data">';
myForm += '</form>';
$("body").append(myForm); // temporarily appending
$("#myData-form").submit(); // submitting form with data
$("#myData-form").remove(); // remove form after submit
And as you said, force download will force file to download and page will remain same. However, if an error occurs, your page will change of course.
I don't know whether this is an effective way or not but in my case, this does the trick.
Old question, but I was trying to do something similar with Laravel PDF extension, and stumbled across this question. I did successfully do this asynchronously with the help of a nice blog post
https://nehalist.io/downloading-files-from-post-requests/
https://github.com/nehalist/download-post-requests
The using the form method, like the previous answer works fine too, but maybe this will help anyone else trying to achieve this with AJAX. The author's XMLHttpRequest method worked great for me!
The code that worked for me (almost verbatim from the blog post) ->
document.getElementById('exportpdf').addEventListener('click', function () {
var request = new XMLHttpRequest();
request.open('POST', '/your/post/endpoint/here', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';
request.onload = function() {
if(request.status === 200) {
var disposition = request.getResponseHeader('content-disposition');
var matches = /"([^"]*)"/.exec(disposition);
var filename = (matches != null && matches[1] ? matches[1] : 'file.pdf');
var blob = new Blob([request.response], { type: 'application/pdf' });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};
I tried to get it to work with jQuery AJAX but failed, so I went with XMLHttpRequest. With jQuery, The download would work, but the content was always empty. I tried to do something like in this post -
https://keyangxiang.com/2017/09/01/HTML5-XHR-download-binary-content-as-Blob/
$.ajax does not support either arraybuffer or blob as its dataType. Thus we need write a beforeSend handler:
//setup ajax
$.ajaxSetup({
beforeSend:function(jqXHR,settings){
if (settings.dataType === 'binary'){
settings.xhr().responseType='arraybuffer';
settings.processData=false;
}
}
})
//use ajax now
$.ajax({
url:url,
dataType:"binary",
success:function(data){
console.log(data); //ArrayBuffer
console.log(new Blob([data])) // Blob
}
})
But never got it to work. Maybe someone smarter can figure out the jQuery method :)

Grabbing div content and sending to php email

New here and glad to be, I've gotten a lot of answers from this forum. I am however stuck at the moment.
I have some javascript that is creating a window color and handle picker (click on the color swatch it changes the image, click on a handle and it does the same). Below the image is a description of the window selected. This text is being generated by the javascript by pulling the image titles.
Now the fun part. Below this picker I need to add a form that will be emailed using php. Within that email I need to pull the window description that is being generated by the javascript.
I have tried so many things today I have lost count. The last bit of code I tried was
<script>
$(document).ready(function() {
$("windowDesc").each(function() {
var html = jQuery(this).html();
});
});
</script>
And in the php mail file I added:
$windowtitle = $_GET['html'];
as well as trying
$windowtitle = $_POST['html'];
and I have also tried the following:
<script>
var content = $('#windowDesc').html();
$.ajax({
url: 'send_mail.php',
type: 'POST',
data: {
content: content
}
});
</script>
And in the php mail file I added:
$windowtitle = $_GET['content'];
as well as trying
$windowtitle = $_POST['content'];
Not to mention a plethora of other things.
Basically what I am trying to do is grab the content of the div that holds the generated text and email it. If any of the above are correct then I must be placing them in the wrong position or something. With the first one I have tried it inside the form, outside the form, before the div, after the div. Just haven't tried it on top of my head yet. It's been a long day, thanks in advance :o)
Sorry for the delay, been a busy two days. OK, so here is the code that handles the window color and handle picker:
var Color = "color";
var Handle = "handledescription";
var ColorDesc = "color";
var HandleDesc = "handle description"
function Window(Color,Handle,ColorDesc,HandleDesc) {
$('#windowPic').animate({opacity: 0}, 250, function () {
thePicSrc = "http://www.site.com/images/windows/" + Color + Handle + ".jpg";
$('#windowPic').attr('src', thePicSrc);
$('#windowDesc').html("<p>" + ColorDesc + " frame with " + HandleDesc + " hardware</p>");
$('#windowPic').animate({opacity: 1}, 250)
})
}
$(document).ready(function() {
$('#wColors li').click( function() {
Color = $(this).attr('id');
ColorDesc = $(this).attr('title');
Window(Color,Handle,ColorDesc,HandleDesc);
});
$('#wHandles li').click( function() {
Handle = $(this).attr('id');
HandleDesc = $(this).attr('title');
Window(Color,Handle,ColorDesc,HandleDesc);
});
});
You need a hidden input in your form:
<form id="send_email" action="send_email.php">
<input id="content" type="hidden" name="content"/>
... other inputs here
</form>
Then you can use Javascript to fill it in before submission:
$("#send_email").submit(function() {
$("#content").val($("#windowDesc").html());
}
<script>
var content = $('#windowDesc').html();
$.ajax({
url: 'send_mail.php',
type: 'POST',
data: content
});
</script>
It worked here.

Drag and drop files (without live upload) / Sending e.dataTransfer.files through form

I'm working on a new drag-and-drop files plugin, however , unlike all those plugins out there
I don't want it to upload it as it "dropped".
The idea is:
1.The user drags and drops the files.
2.(Some Magic)
3.The user submit the form and only than those files getting uploaded to the server
I tried appending the file's name to the form as an input type=hidden , however I can't do anything with it on the server side (php);
Can I append the file's details to a input type=file field some how so the browser will "think" the file has been selected via regular file input field
My js:
$('#drop-zone').bind('drop', function(e) {
// This variable represents the files that have been dragged
// into the drop area
var files = e.dataTransfer.files;
$('#uploaded-list').show();
// For each file
$.each(files, function(index, file) {
/* What can I do in here?*/
});
});
Thanks.
Maybe you've already solved this, but I figured this out today.
This would not be IE9- compliant (but then again, neither are drag and drop files), but you could store the dataTransfer.files data, and when you're ready to submit, create a FormData from the form and append the files.
var formData = new FormData(html_element_of_form); //not a jq obj!
for (var i = 0; i < files.length; i++) {
formData.append('file', files[i]);
}
// now post a new XHR request
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
xhr.onload = function () {
if (xhr.status === 200) {
console.log('all done: ' + xhr.status);
} else {
console.log('blarrghhhhh...');
}
};
xhr.send(formData);

JQuery, AJAX, PHP, XML; Image overlay script stops working on callback content

A button click fires my function that fetches image data via an AJAX-call:
$("#toggle_album").click(function () {
album_id = $("#album_id").val();
$.post('backend/load_album_thumbnails.php', {
id: album_id
}, function(xml) {
var status = $(xml).find("status").text();
var timestamp = $(xml).find("time").text();
$("#album_thumbs_data_"+album_id+"").empty();
if (status == 1) {
var temp = '';
var output = '';
$(xml).find("image").each(function(){
var url = $(this).find("url").text();
temp = "<DIV ID=\"thumbnail_image\">[img-tag with class="faded" goes here]</DIV>";
output += temp;
});
$("#album_thumbs_data_"+album_id+"").append(output);
} else {
var reason = $(xml).find("reason").text();
var output = "<DIV CLASS=\"bread\">"+reason+"</DIV>";
$("#album_thumbs_data_"+album_id+"").append(output);
}
$("#album_thumbs_"+album_id+"").toggle();
});
});
The data is returned in XML format, and it parses well, appending the data to an empty container and showing it;
My problem is that my image overlay script:
$("img.faded").hover(
function() {
$(this).animate({"opacity": "1"}, "fast");
},
function() {
$(this).animate({"opacity": ".5"}, "fast");
});
... stops working on the image data that I fetch via the AJAX-call. It works well on all other images already loaded by "normal" means. Does the script need to be adjusted in some way to work on data added later?
I hope my question is clear enough.
Okay, apparantly I hadn't googled it enough. Surfing my own question here on stackoverflow pointed me to other questions, which pointed me to the JQuery live() function: live().
However, it does not work on hover(), so I rewrote the script to use mouseover() and mouseout() instead:
$("img.faded").live("mouseover",function() {
$(this).animate({"opacity": "1"}, "fast");
});
$("img.faded").live("mouseout", function() {
$(this).animate({"opacity": "0.5"}, "fast");
});
... and now it works flawlessly even on the content I fetch from the AJAX-call.
Sorry if anyone has started writing an answer already.
You have to bind the new events each time you add a DOM element to the page.
There is a built-in function in jquery called live that does that for you.
I noticed you add the images from your xml; you can add there the new binds too.
$(xml).find("image").each(function(){
//this actually creates a jquery element that you can work with
$('my-img-code-from-xml-goes-here').hover(
function() {
$(this).animate({"opacity": "1"}, "fast");
},
function() {
$(this).animate({"opacity": ".5"}, "fast");
}
//i did all my dirty stuff with it, let's add it where it belongs!
).appendTo($('some-already-created-element'));
});
EDIT: corrected a wrong sentence.

Categories