fine uploader changing the input name to match what my script is expecting - fine-uploader

I am incorporating Fine Uploader into a form that already exists.
I've added three Fine Uploader file upload fields. I have one script that controls all three of the boxes. I looked at the inputName attribute and attempted to change that, but it changed the name of all of the fine upload fields to what i set as the inputName (in this case it was photo1). That's not exactly what i want. I want to set the inputName for each field to something different.
In my case, it is important that I have 3 individual boxes because I have a message box that goes with each photo.
I mainly just want to use Fine Uploader for its ability to allow iphone users to select a photo if they are on the phone and also for the thumbnail preview after the photo is selected. All that stuff is great.
The rest of the form I have is already functioning and I can submit it using standard input file fields.
Questions:
Is there a way to use multiple fields on a single page? Do I need to
write a seperate $('#photo1').fineUploader(){...}); per input box?
Is there a way to change the input name for each file upload field?
I assume i can achieve this with seperate script blocks, but is
there a better/cleaner than repeating all that code?
I downloaded the PHP Server Handler files and when i submit my test form with interceptSubmit: true, I see the images upload to my server. That works. (i kinda made a simple form just to test it out). When i change to interceptSubmit: false, add a page called thankyou_post.php as my post action page and in that page I'm just seeing what the form is sending by print_r($_POST); and all i get is Array ( [submit] => submit ) as the response.
I suppose my next step will be to try to write custom blocks per file field and see if the form can process that better.
$(document).ready(function () {
$('#photo1, #photo2, #photo3').fineUploader({
debug: true,
template: "qq-dav-photo-with-thumb",
thumbnails: {
placeholders: {
waitingPath: "placeholders/waiting-generic.png",
notAvailablePath: "placeholders/not_available-generic.png"
}
},
form: {
interceptSubmit: false
},
camera: {
ios: true
},
request: {
endpoint: 'thankyou.php',
paramsInBody: true,
inputName: 'photo1'
},
messages: {
emptyError: 'File is empty',
noFilesError: 'No files attached.',
onLeave: 'We are still uploading your files...Please wait.'
},
validation: {
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'],
itemLimit: 3,
stopOnFirstInvalidFile: true
}
}).on('progress', function (id, fileName, uploadedBytes, totalBytes) {
console.log('progress...');
}).on('complete', function(event, id, fileName, responseJSON) {
if (responseJSON.success){
file_name = responseJSON.name;
console.log('hoorah! File name: '+file_name);
};
}).on('allComplete', function(event, id, fileName, responseJSON) {
console.log('hoorah! All complete!');
});
});
Any thoughts on what i can do to make this work?
UPDATE #1
LINK: http://ijwebsites.com/fineuploader/
This is the HTML on my form page.
<form action="thankyou_post.php" method="post"
id="qq-form" name="webform" enctype="multipart/form-data" >
<!-- Fine Uploader DOM Element
====================================================================== -->
<div id="photo1"></div>
<br>
<br>
<div id="photo2"></div>
<br>
<br>
<div id="photo3"></div>
<input type="submit" name="submit" value="submit">
</form>
And my thankyou_post.php page for my test page is very basic, i just want it to tell what values were submitted to the page so i am doing on that page:
<?php
if ($_FILES["photo1"]["error"] > 0) {
echo "Error: " . $_FILES["photo1"]["error"] . "<br>";
} else {
echo "Upload: " . $_FILES["photo1"]["name"] . "<br>";
echo "Type: " . $_FILES["photo1"]["type"] . "<br>";
echo "Size: " . ($_FILES["photo1"]["size"] / 1024) . " kB<br>";
echo "Stored in: " . $_FILES["photo1"]["tmp_name"];
}
?>
When I submit the form, i get a message "Error: 4". What do you think the problem is?

If you'd like to have multiple uploaders on the same page, and have varying options for each uploader (in this case, a differing request.inputName option), you'll need to initialize each instance separately. You can combine initialization into a common function that takes the input name as a parameter, if you'd like.
If you want Fine Uploader to send the entire contents of your form, including the selected files, ensure the form.interceptSubmit option is set to true (this is the default anyway). If you do not want this to happen, and you want to upload selected files in a separate request, then you should not enable form support at all in Fine Uploader. Form support was created for those who want Fine Uploader to completely manage a form.
It's not clear from your question what your form or forms look like, as you have left out your markup. If you are expecting Fine Uploader to control multiple file input elements in a single form, then you will need to make use of the extraButtons option.

Related

Upload multiple files, picking them one by one, with BootstrapVue b-form-file

I'm uploading files with b-form-file in BootstrapVue, setting multiple to true works perfectly for multiple files, BUT each time I choose a file it removes any previously added ones. And the files will often be spread across multiple folders, so I need to be able to pick a file from one folder, choose it, pick another file from another folder, and so on.
Here's the HTML:
<b-form ref="form" novalidate action="upload" method="post" enctype="multipart/form-data">
<b-form-file name="file_upload[]" :multiple="true" :file-name-formatter="formatAssetUpload" no-drop placeholder="Click to choose"></b-form-file>
</b-form>
I've tried adding
ref="fileUpload"
to the b-form-file tag and then in the formatAssetUpload function just setting the value, but that doesn't work. There's a setFiles function in there but it doesn't seem to affect anything. I tried catching the form on submit and manually adding the files to formdata but that's not working either, whatever I try there's always only the last file/files that were picked coming through on the backend.
Any ideas?
Thanks for any help! :)
If you like to remember the file objects which have been selected by the user you an use this javascript:
new Vue({
el: '#app',
data() {
return {
files: [],
filesAccumulated: []
}
},
methods: {
onChange(event) {
this.files.forEach(thisFile => {
this.filesAccumulated.push(thisFile)
})
},
onReset() {
this.filesAccumulated = []
}
}
})
Together whit this vue template
<div id="app">
<b-form-file
v-model="files"
multiple plain
v-on:input="onChange">
</b-form-file>
<div>
<ul>
<li v-for="thisFile in filesAccumulated">
{{ thisFile.name }}
</li>
</ul>
</div>
<b-button v-on:click="onReset">
Reset
</b-button>
</div>
The b-form-file vue component is emitting an input event when the user performs the selection. The file objects can be picked up
from the variable bound with the v-model directive. See documentation
Look at this fiddle https://jsfiddle.net/1xsyb4dq/2/ to see the code in action.
General comments
Let me make some comments on your code example and b-form-file component in general: With bootstrap-vue and <b-form-file> it is not the idea to use an enclosing form tag to submit forms. Instead you use vue's v-model feature to obtain the file objects from vue's data object.
I have created a more comprehensive example here https://jsfiddle.net/to3q7ags/ , but I will explain step by step:
The value of the v-model attribute is the name of a vue data property:
<b-form-file v-model="files" multiple plain></b-form-file>
After the user has clicked 'Browse' in the file input field, has selected the files and pressed ok, the vue data property will hold an array of file objects:
new Vue({
el: '#app',
data() {
return {
files: []
// initially empty, but will be populated after file selection
}
}
})
From the b-form file documentation:
When no files are selected, an empty array will be returned. When a
file or files are selected the return value will be an array of
JavaScript File object instances.
After files are selected by the user you can send the files to your server on a button click or change event.
<b-button v-on:click="onSubmit">
Submit
</b-button>
the corresponding vue method looks like this
methods: {
onSubmit() {
// Process each file
this.files.forEach(thisFile => {
console.log("Submitting " + thisFile.name)
// add submit logic here
}
}
To submit the files you need to manually create a http post request which is using the multipart/form-data encoding. That can be done by using FormData class.
const formBody = new FormData()
formBody.set("formParameter", thisFile)
The FormData.set() method is accepting file blobs as arguments. Then you can use XMLHttpRequest.send() or fetch() to send the post request:
fetch(
"https://yourserver/post",{
method: 'POST',
body: formBody})
.then(response => console.log(response))
Now all selected files are posted to the server. The user can repeat the process with the same form, select new set of files and again press the post button.
You can also send the form automatically without the use of a button by listening to the 'input' event. Drag and drop also works.

check in blade view if image is loaded or 404

Is there a way to check in a blade view if an image is really there or not?
I need to show results from a search box.
The results are many boxes with infos and a picture for each box.
The point is in my DB I store links to images that are on remote servers and also name of images that are stored locally.
So what I am doing is check if the file exists locally and if so use it and if not look on the remote server (if the picture data is not NULL it's either there or in a remote server).
I was trying to check if file exists using curl and it works but for big collections it takes too much time to finally spit the data to the view (every link has to be checked).
So what I want to do, if possible, is check directly in the blade view if the picture is not broken (404) and if so replace with an "image-not-found.png" I store locally. How can I do that?
I usually handle this with JavaScript using the img tag's onerror event. Typically I add a few more bells and whistles to the solution but this is it in a nutshell.
Plan JavaScript
function loadNextImage(id,uri){
document.getElementById(id).src = uri;
}
Plain HTML
<img src="http://local/image.jpg"
onerror="loadNextImage('image1', 'http://remote/imae.jpg'));"
id='image1' />
VueJS and Webpack
<template>
<img :src="local_url" #error="imgOnError()" ref="image"/>
</template>
<script>
export default{
name: 'Thumbnail',
props: {
local_url: String,
remote_url: String
},
methods: {
imgOnError: function (e) {
this.$refs.image.src = this.remote_url
}
}
}
</script>
You can use the func "file_get_contents" inside a try-catch block. I know i not the best way, but i could work for you.
Tray this (no the best way):
<?php
try{
$img = 'myproject.dev/image.jpg';
$test_img = file_get_contents($img);
echo "<img src='{$img}'>";
}catch(Exception $e){
echo "<img src='img/no-img.jpg'>";
}
?>

AJAX file upload in Play Framework 2.1 RC1 delivers an empty file

Scala/Play gurus out there.
I'm trying to upload a file using AJAX, in Play 2.1 (RC1). For the client part I'm using eldarion/bootstrap-ajax and everything seems to be fine, except that the uploaded file is empty.
The front-end snippet:
...
<form action="#routes.Campaigns.upload" method="post" class="form ajax replaceable" data-replace=".replaceable">
<input type="file" name="picture">
<p><input class="btn" type="submit"></p>
</form>
...
Note that I had to use the explicit <form> tag instead of the #form helper, due to the fact that the required css class (data-replace) contains a dash, and therefore can not be used as a Symbol. But anyway. The called action in the controller looks like this:
def upload = Action(parse.temporaryFile) {
request =>
Logger.info("Trying to upload a file")
val resultString = try {
val file = new File("/tmp/picture")
request.body.moveTo(file, true)
"file has been uploaded"
} catch {
case e: Exception => "an error has occurred while uploading the file"
}
val jsonResponse = Json.toJson(
Map("html" -> Json.toJson("<p>" + resultString + "</p>")
)
)
Ok(jsonResponse)
}
I'm aware that as my development goes forward the file name should be more intelligently set, but for the moment being, /tmp/picture is for me as good a name as any other one.
The JSON response gets generated (with the "file has been uploaded" message within), and is sent back to the browser as the payload of the 200 response. The JSON is received and correctly used to modify the page (in this case, merely removing the very uploading form).
But the file, although appearing in the right moment and in the right place, is always empty:
larsson:tmp bruno$ ls -l /tmp/picture
-rw-r--r-- 1 bruno staff 0 7 Jan 03:07 /tmp/picture
That's specially strange, in my opinion, because the uploading code which uses a traditional multipart/form-data form, with no AJAX whatsoever, and an Action with parse.multipartFormData as a parameter, instead of parse.temporaryFile, works finely.
Any help will be very appreciated. Thanks in advance.
I don't know bootstrap-ajax, anyway if it hasn't dedicated support for uploading files via AJAX (and I didn't find any info about that possibility in its readme file) it will NOT send files with AJAX.
Reason: In standard JavaScript uploading files with AJAX is not possible due the security limits and there are some techniques to workaround this, mainly using iFrames, however I can't see nothing similar in the code of bootstrap-ajax so probably you need to modify it or use other solution.
Solution: There are some AJAX file uploaders, which works good with HTML5 ie. jQuery File Upload, which offers ajax upload, multi-file uploads, drag file to the drop zone etc.
In general HTML5 supports file uploads better than earlier versions of HTML, so you can build uploader easily without need of using additional plugins, take a look to this topic. As you can see it delivers possibilities to validate some data BEFORE the upload and also offers progress bars.
I'm currently trying to implement something like this and I got a first version working. This is how I do it:
In my Controller I define a method for uploading files. In my case I use Action.async since I save stuff to my MongoDB with reactivemongo. I have removed that code so that it do not complicate this example.
What I do in this example is that I upload a csv file, save it to disk and then produce the first row back as a string to the user. In real life the method produces a list back so that user is able to choose which column represent what an so on.
I use mighty csv for csv parsing. GREAT LIB!
Application:
def upload = Action.async(parse.multipartFormData) {
implicit request =>
val result = uploadForm.bindFromRequest().fold(
errorForm => Future(BadRequest(views.html.index(errorForm))),
form => {
import java.io.File
request.body.file("csvFile").map {
csv =>
val path = current.configuration.getString("csv.job.new.file.path").getOrElse("")
val name = DateTime.now().getMillis + ".csv"
csv.ref.moveTo(new File(path + name))
val settings = CSVReaderSettings.Standard(linesToSkip = form.linesToSkip)
val rows: Iterator[Array[String]] = CSVReader(path + name)(settings)
val firstRow = rows.next()
val test = firstRow match {
case xs if xs.size == 0 || xs.size == 1 => xs.mkString
case xs if xs.size > 1 => xs.mkString(", ")
}
Future(Ok(test))
}.getOrElse(Future(BadRequest("ahadasda")))
}
)
result
}
routes:
POST /upload #controllers.Application.upload
I use # before the controllers because I use DI with guice for my service classes.
Since we will use javascript for uploading we need to define our jsRoutes:
jsRoutes:
def javascriptRoutes = Action {
implicit request =>
import routes.javascript._
Ok(
Routes.javascriptRouter("jsRoutes")(
Application.upload
)
).as("text/javascript")
}
Remember to import in your template where you want to use the routes:
<script type="text/javascript" src="#routes.Application.javascriptRoutes"></script>
<script src="#routes.Assets.at("javascripts/app.js")#Messages("js.version")" type="text/javascript" ></script>
In my view template I have a regular helper form. There is some css style stuff I do to
change the looks and feel of the upload button and file chooser. But the input fields
are there.
index.scala.html:
<div class="csvContainer">
#helper.form(action = routes.Application.upload, 'enctype -> "multipart/form-data", 'id -> "csvUpload") {
#Messages("upload.row.skip")
#inputText(uploadForm("linesToSkip"), 'class -> "hidden")
<div style="position:relative;">
<div id="csvFile" style="position:absolute;">
#Messages("upload.choose")
</div>
<input id="uploadFile" type="file" name="csvFile" style="opacity:0; z-index:1;" onchange="document.getElementById('csvFile').innerHTML = this.value;" />
</div>
<p>
<input type="submit" value="#Messages("upload.submit")">
</p>
}
</div>
In app.js is where the ajax magic happens, remember I have not implemented any validation or cool html5 stuff yet as the progressbar and other handlers, described in besiors link.
I use regular JQuery.
app.js:
$('#uploadFile').change(function(){
var name = $(this).val().split("\\");
console.log(name[2]);
$('#csvFile').text(name[2]);
});
$('#csvFile').click(function(){
$('#uploadFile').click();
});
$("#csvUpload").submit(function(e) {
e.preventDefault();
var formData = new FormData();
formData.append('csvFile', $( '#uploadFile' )[0].files[0]);
formData.append('linesToSkip', $( "#linesToSkip").val());
jsRoutes.controllers.Application.upload().ajax({
data: formData,
processData: false,
contentType: false,
cache: false,
type: 'POST',
success: function(data){
alert(data);
}
});
});
I have removed a lot of code to simplify this example and I hope that I have not forgotten anything. Hope this helps!

How to make sure a file is selected before uploading

Hi I am using codeigniter for file uploading and I am using this code
echo form_open_multipart('controller_a');
echo form_upload('userfile');
echo form_submit('Upload','upload');
echo form_close();
I store the pointer to the uploaded file in the database,
My question is how do I make sure that the user has selected a file before clicking on upload button because as of now the code submits even if the user clicks directly on upload without selecting a file
Along with client side verification, you should use server side verification, too. Currently, CodeIgniter does not provide a function, so one can use native PHP function is_uploaded_file:
if (is_uploaded_file($_FILES['myfile']['tmp_name']))
{
$this->load->library('upload');
$this->upload->do_upload('myfile');
}
You can't, not in CodeIgniter at least. You'll need to have JS overwrite the onsubmit property of the form and then test the userfile input's value.
use JS
very basic code, but it works.
<script type="text/javascript">
<!--
function validate_form ( )
{
valid = true;
if ( document.upload_form.something.value == "" )
{
alert ( "Please select a file before clicking upload ! " );
valid = false;
}
return valid;
}
//-->
</script>
and use onsubmit even in the form
onSubmit="return validate_form ( );"
when a user click on upload button without selecting any file, it will alert the user .
Your best bet is to use a jQuery plugin like the following:
http://bassistance.de/jquery-plugins/jquery-plugin-validation/
This will allow you to select what input values will need to be selected, and customize a message to inform the user what field(s) they are missing.

use html5 multiple attribute to trigger multiple single uploads

Sorry for the confusing title.
I have a form-- form1 that has one file input ( with multiple attribute set so that user can select mutiple files). The form doesn't get submitted.
I have another form -- form2 that has a single file input . no mutiple attribute.
Now via javascript i would like to fetch each files from the fileinput from the previous form and then assign the file to the form2's input field and then do an ajax submit.
Once the ajax submit is complete I would like to do the same to 2nd file and then 3rd file and so on.
I don't want to use flash or java applet.
I am fully aware that IE doesn't support multiple attribute
opera can use invalid min max attribute to do the same.
My basic question would be how to fetch the files from the form1 input field and then assisgn it to form2's field ..
Is there a solution for this ?
or is my approach itself incorrect ?
What I want to achieve on UI side ?
The file gets uploaded and server does some processing and returns some data.
so what I want is user can select 10 files but as soon as 1st file is uploaded the output is received.
First : My idea is wrong.
We cannot assign a value via javascript to the input with type = file .
I thought of another idea using the XMLHttpRequest.
here is my code :
<form id="new_picture_form" method="post" enctype="multipart/form-data" action="some url" accept-charset="UTF-8">
<input id="original_input" class="file_hidden" type="file" onchange="handleFiles(this.files);" name="picture[image][]" multiple="multiple">
</form>
<form id="fileinfo" method="post" enctype="multipart/form-data" action="some url">
</form>
<script type="text/javascript">
function handleFiles(files)
{
for (var i = 0; i < files.length; i++) {
FileUpload(files[i])
}
}
function FileUpload(file) {
var data = new FormData(document.getElementById("fileinfo"));
var xhr = new XMLHttpRequest();
this.xhr = xhr;
data.append('some field',"that you want to pass as param ")
data.append('type',"picture")
data.append("picture[image]", file);
xhr.open("POST", "URL",true);
xhr.send(data);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
eval(xhr.responseText) // basically the result from server contains some script
}
}
}
</script>

Resources