Remember a file upload on form submission - php

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>

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.

$_FILES does not accept value [duplicate]

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.

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.

Attach file to form on redirect

Im providing a file preview option, where the user attaches a file, and then clicks preview.
Which uploads the file, and outputs a PHPExcel preview.
From that page, I want to include a button that says continue.
Which will then proceed with the actual upload and database row creation.
However once I redirect to the preview page, I have no idea how to attach this file to my hidden form for resubmission.
I can attach all the old input values....like so...
But how do I attach the file??? (using blade in laravel for templating)
/* These work and are correct*/
<input type="text" id="xlsColumnOrder" name="xlsColumnOrder" value="{{$input['xlsColumnOrder']}}"/>
<input type="text" name="researcher" value="{{$input['researcher']}}" />
<input type="text" name="leadcity" value="{{$input['leadcity']}}" />
<input size="16" id="survey_date" name="survey_date" type="text" value="{{$input['survey_date']}}" />
/* This doesnt attach anything to the file input
/* Need to attach the previously uploaded file here for resubmission */
<input class="file" id="csvfile" name="csvfile" type="file" value="{{$file['csvfile']['tmp_name']}}" />
You cannot automatically resend user files so I would do it this way:
When user sends form if any file is provided you save file in some directory (you treat it as temporary) and save file name/names to session and show user preview of file
When he clicks continue - you can do with other data whatever you want (for example save it to database or show as hidden in another form) and you still have uploaded filename in session so if you want you may even again show file preview
When you want to finally save all user data you move user file/files to final directory (and possible rename it) and save all the data with file(s) name (probably in database).
As addition you should have some kind of cron that removes data from your temporary directory that very created for example more than 3 hours

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