$_FILES does not accept value [duplicate] - php

I have a form with text inputs and file inputs; the text fields are being validated. Is there a way to have the form remember which files the user has already selected if they hit submit but need to go back because one of the text fields didn't validate?

You can't "pre-fill" the contents of a file upload field for security reasons. Also, that would mean the file would get re-uploaded every time the form is submitted, which would not be good.
Instead, do this:
Create a file upload field with name file_upload.
On the server-side, process the upload in any case, even if the rest of the form validation fails.
If the form validation failed, but the file was uploaded, insert a hidden input into the form with name file containing the name of the just uploaded file.
Display a user-visible indication that the file is okay. If it's an image, display a thumbnail version of it. If it's any other file, display its filename and/or icon.
If the user chooses to upload a different file in the file_upload field, process the upload and store the new value in file.
Pseudocode:
<?php
$file = null;
if (!empty($_POST['file'])) {
$file = $_POST['file'];
}
if (!empty($_FILES['file_upload'])) {
// process upload, save file somewhere
$file = $nameOfSavedFile;
}
// validate form
?>
<input type="file" name="file_upload" />
<input type="hidden" name="file" value="<?php echo $file; ?>" />
<?php
if (!empty($file)) {
echo "File: $file";
}
?>
Important note
This mechanism can allow any user to claim other user's files as their own, by including a file name that they guessed exists on your server. You will want to ensure that uploaded files are clearly associated with a specific user to avoid this issue.

files input fields are read-only you can't set an initial value for them

You can upload the Files anyway and display the filenames instead of the file select box. To remember the fields, you can use a $_SESSION variable.

Related

Keep in memory submitted file until form is valid and clean up

Do you have an elegant solution to validate server side a form containing more than one input type file under these conditions:
If one file is not valid user will have to upload another
If one file if valid the server should keep it in memory so user don't have to upload it again.
Valid file should be shown on the form
User may just abort and leave the page. Whatever has been saved on the server should be deleted.
As I example let's take a form containing 1 input type text and 2 inputs type file.
<input type="text" name="title" />
<input type="file" name="file1" />
<input type="file" name="file2" />
User submit a valid title, a valid file1 but invalid file2.
The goal here is to save each valid file until the form is valid or until session expires or something expires :)
Suggestion 1
Generate a unique key for the user form (i.e form123) create a directory /tmp/uploads/form123 where valid file are saved.
A cron running every 10min go through all directories in /tmp/uploads/ and delete the one existing for more than 10min.
With this suggestion the big question is how to clean up the system if user abandon the form.
I think you're on the right track with your suggestion. keep track of valid/invalid entries for the user (you don't even have to save it to disk, just grab the reference and store it in the $_SESSION global), and adjust the form based on that.
if the form is invalid, store the submitted, valid files in $_SESSION
<?php
// ... if the form is invalid
if (isset($_SESSION['file_1']) { ?>
<!-- show a placeholder -->
<!-- i.e. something saying 'file 1' and its name or whatever -->
<?php } else { ?>
<!-- show the input -->
<?php } ?>
Then, when the form is finally valid, combine the values you have stored in $_SESSION with the information submitted to produce the final, valid form.

Fill file input after form submit / on form submit error

I´ve a multipart form with a mixture of default inputs (text, select etc.) and a file upload (<input type="file">).
I´m using a combination of form validation class and upload library of Codeigniter for form submission. That works great.
I´ve only one problem for what I haven´t found a solution yet: If the user selects an image but misses to fill another required field (like "name"), then the form validation class blocks the request and shows an error message to the customer.
But now I´ve the problem, that the image was already submitted successfully and I don´t want to let the user add the file again. So I want to pre-fill the file input with this data.
I´ve tried different things like:
<input type="file" name="image" value="<?php echo set_value('image','');?>" />
and also spent time on finding a solution on the web but without success.
On the server side, you do not get any information about where the file is located on the client's computer, so in the scenario of a user uploading an image successfully but the user hasn't filled out the rest of the fields properly, you have to simply omit the input type="file" field entirely but keep a store of where the file is located on your server. There's a few ways to go about this, but it all involves taking the absolute location of the uploaded file and:
Inserting it back as a hidden value using <input type="hidden" name="uploadedFile" value="<?php echo $absPath; ?>" /> then checking for the existence of $_POST['uploadedFile'] and utilizing it appropriately. But this isn't a solid idea as you're now exposing server paths to the end-user (opens yourself up to malicious attack.)
Starting a session and saving the absolute path in the $_SESSION variable while presenting the user with a simple token in their re-attempt form.
I'd stick with method 2, so assuming you've done all the work to validate the form and upload the file and your file is located in $absFilePath, you could do the following:
session_start(); // This needs to be at the very top of you PHP file
// ...
$formToken = md5(time());
$_SESSION['uploadedFile'][$formToken] = $absFilePath;
Then render the token as a hidden variable using:
if (!empty($_SESSION['uploadedFile'][$formToken]))
echo '<input type="hidden" name="formToken" value="'.$formToken.'" />';
and hide the file upload portion using
if (empty($_SESSION['uploadedFile'][$formToken]))
echo // <input type="file" output here...
finally inside of your form submission code check for the existence of a formToken value before attempting to load $_FILES['image'] using isset($_POST['formToken']), and handle it using:
$absFilePath = $_SESSION['uploadedFile'][$_POST['formToken']];
Bam! Now you have your absolute file path as if the file had been uploaded just like before.
Since you haven't given enough code, I can only given you enough instruction to get you started, but this should be more than enough.

Remember a file upload on form submission

I'm using codeigniter and jquery to create a form that takes text values and a single file upload.
I want it so that if the form validation fails, the uploaded image is still visible to the user, but I'm at a loss now about how to do this without issues popping up.
My current solution is uploading the image regardless if the form validated or not, and then checking if a file with the same name as the name in $_FILES exists, and serving that. But this leads me to a problem with duplicates. I'm appending duplicate file name with a number (eg. file2.jpg), but that means the file uploaded will always find the image name "file.jpg" even if the file the user uploaded with allocated the name "file3.jpg".
There must be a simpler way.
How about save file with hashed name md5(name+actualTimestamp) and save this file name to user session (you could save this filename in cookies or use session mysql table with serialized session data).
How about you assign a unique id to the form, probably a combination of year, month, day, hour, minute and seconds then move uploaded image to a temp directory on your server, save the image with the same name as the form id....
your code should be something like:
<form method="post" action="process.php">
<input type="hidden" name="form_id" value="<?php if(isset($_POST['form_id'])){ echo $_POST['form_id']; }else{ echo date("Ymdhis"); }" />
<!-- other form objects goes here -->
</form>

Pass uploaded file between PHP scripts

I've got a page where users can upload a HTML file for use as a theme. The HTML file has some checks performed on it before some options are displayed to the user. The user fills out the form in relation to the HTML file, and submits the form. However, due to the file in the temp folder being destroyed after the script has ended, I do not know how to get the HTML file once the form has been filled out and re-submitted short of making the user re-upload the file, which relies on them uploading the same file, and also makes them upload something twice, which is counter-intuitive and could be an issue with large files.
Here is the code (cut down to make it easier to read/understand). The form submits to itself, so the same PHP file is used for both "steps".
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Form has been submitted
$files = $_FILES['file'];
<form method="POST">
/* Options about the uploaded HTML file are generated using PHP and displayed here */
<input type="submit">
</form>
} else {
?>
<form method="POST" enctype="multipart/form-data">
<label for="file">Theme File(s)</label>
<input type="file" name="file[]" multiple="multiple">
<input type="submit">
</form>
<?php
}
I tried using <input type="file" name="file[]" multiple="multiple" value="<?php echo $files; ?> >, but this did not work, and would also require the user to re-upload the files, which could be any issue if the files get too big.
I was thinking there might be a way to pass the file internally, and have a check whether a file has been uploaded or passed to the script instead of <input type="file" name="file[]" multiple="multiple">, but I could not find a way to do that.
You need to create your own temporary file, and pass the name between your two scripts.
So for example, in your "first script" (i.e. when the file has first been uploaded) you would:
$uniqName = uniqid('upload_', TRUE);
$tmpFile = "/tmp/$uniqName.html";
move_uploaded_file($_FILES['file']['tmp_name'][0], $tmpFile);
And then when you generate the form from the result of this upload, you would add
<input type="hidden" name="uniqName" value="<?php echo $uniqName; ?>" />
...so that when you get to your "second script" (after the questionnaire form is submitted) you can access the file through:
$tmpFile = "/tmp/".basename($_REQUEST['uniqName']).".html";
Of course, this is subject to the possibility of people failing to submit to second form so you end up with "orphaned files" littering your temporary directory, so you will need to implement some form of check that deletes files after thet have been inactive for a certain amount of time - you can base this on the last modified time of the files.
EDIT
Here is an example of how you can randomly run a job to keep the /tmp dir tidy without a cron job:
$probabilityDivisor = 10; // 1/10 chance of running
$uploadTTLSecs = 1800; // 30 minutes
if (mt_rand(1, $probabilityDivisor) / $probabilityDivisor == 1) {
foreach (glob('/tmp/upload_*') as $file) {
// Iterate files matching the uniqids you generate
if (time() - filemtime($file) >= $uploadTTLSecs) {
// If file is older than $uploadTTLSecs, delete it
unlink($file);
}
}
}
This operates in a similar way to the PHP session garbage collectors. Because of the simplicity of the operations, this should not adversely affect the user experience in any meaningful way.
You could try the following:
Use move_uploaded_file() and move the file from the temp location to a permanent location on the server. Be sure to give the file your moving a unique name like 'file-' . time() . '.jpg' or something.
Soon after uploading, register a Session variable and put the file name in it.
After everything is over you could delete the file using unset()
Now the file is located safely on your server and you also have access to it via the session.
Hope this helps :)

How to avoid data loss after server validation in php?

In my create page, i am using one or more file upload text box , select box ,text box inside a form , After filling all form datas and submit, I will do a server validation then insert into db...
Before insert into db, if server validation fails, filled datas are lossed , Is there any easy way to prevent data loss?
for select and text box we can pass the value of $_POST
But for file upload text box , how to prevent data loss? Can we store in session?
Thanks in advance..
well you can use some variables to store the data, then you can perform the validation
well i am giving a example of php validation
<?php
if(isset($_POST['submit'])){
$name = $_POST['name']; //
// and some other data input
and goes the validation part
?>
<form ... >
<input type="text" name="name" value="<?php if(isset($name)) echo $name; ?>"
</form>
well.. this must work..
you might find other better ways.. but this will also work
As per my knowledge you can not maintain the file upload values as like the other form elements.
If you still want to maintain the $_FILES values. You can take them in session.
$_SESSION['imagename'] = $_FILES['image']['name'];
$_SESSION['imagetmp'] = $_FILES['image']['tmp_name'];
You can save the data in variables and populate it later, except for the type="file" input field. It will be a security problem if the files can be prepopulated(or say selected without user permission) and browsers won't allow it.
One option is to save the file in any temporary folder in server and if validations worked fine, move it to the uploads directory.
Another option is to show your form in steps(in pages) and the file upload option in the last step, so that the user will reach the file upload section after all validations and you can do the file upload validation in the last step.

Categories