I wrote below PHP code. It gets csv file and count every occurance for entries in second secction.
It is working nice, when file is given by file name.
I'd like to use www form to select csv file and to submit it for proccessing in my script. No need to save on server side.
I tried to do it in the way which is commented now. Do you have any idea how to do this?
<?php
//$uploaded=$_FILES["file"];
//$file = file($uploaded, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES );
$file = file('dump.csv', FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES );
$amount = count($file);
$name = array();
$qty = array();
$j=0;
$pars=str_getcsv($file[0], ';');
$name[0]=$pars[1];
$qty[0]=1;
for ($i=1; $i<=$amount;$i++){
for ($a=0; $a<=$j;$a++){
$pars=str_getcsv($file[$i], ';');
if ($name[$a]!=$pars[1]){
if($a==$j){
$j++;
$name[$j]=$pars[1];
$qty[$j]=1;
break;
}
}
else {
$x=$qty[$a];
$qty[$a]=$x+1;
break;
}
}
}
for ($b=0; $b<=$j;$b++)
{
echo $name[$b] . $qty[$b] . "<br>";
}
?>
HTML:
<form action="skrypt.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
The uploaded files come in the reserved variable $_FILES with the following format:
array(
"name" => "dump.csv",
"type" => "text/csv",
"tmp_name" => "/tmp/php/php6hst32",
"error" => UPLOAD_ERR_OK,
"size" => 98174
)
"tmp_name" is the filename, so replace the first lines of you code with:
$uploaded = $_FILES["file"]["tmp_name"];
$file = file($uploaded, FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES );
try this
$file = file_get_contents($_FILES["file"]["tmp_name"]);
and then run it through your program normally. Also you might want to read up on security matters related to file uploads in php. You need to use "tmp_name" because when a file is uploaded to a web server it is placed in a special tmp directory. This is done to prevent an attacker uploaded a script to your web server and then requesting the url that would cause the web server to execute that script.
Imagine this scenerio
an attacker writes this in into a file named asgoodasaterminal.php
<?php
echo $_GET['cmd'];
$out = shell_exec($_GET['cmd']);
echo $out;
?>
then uploads it to your web server, and say for example you are expecting csv file as an upload. So you move what you think is a csv file to /var/www/uplaods/csv
next the attacker enters into his browser
http://www.yoursite.com/uplaods/csv/asgoodasaterminal.php?cmd=<any command you want>
The attacker can now do anything the web server user has permission to do.
Related
This is my html form
<form action="index.php" method="post" enctype="multipart/form-data">
Send these files:<br />
<input name="userfile[]" type="file" /><br />
<input name="userfile[]" type="file" /><br />
<input type="submit" value="Send files" />
</form>
This is my index.php file
<?php
foreach ($_FILES["userfile"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
echo"$error_codes[$error]";
move_uploaded_file(
$_FILES["userfile"]["tmp_name"][$key],
$_FILES["userfile"]["name"][$key]
) or die("Problems with upload");
}
}
?>
**The code is working properly. But, What I really need is to change the name of the 1st uploaded file to birthcertificate and the name of the 2nd uploaded file into NIC. **
**Example : If I upload a file named 123 or abc (whatever the name) the 1st file's name should be birthcertificate and the 2nd file's name should be NIC. **
There are probably lots of ways to do this.
I thought that making a list of the new file names
might be the way to go.
<?php
// Make a list of the new file names
$newFileNames = ['birthcertificate', 'NIC'];
foreach ($_FILES["userfile"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
echo"$error_codes[$error]";
// Grab new file name
$newFileName = array_shift($newFileNames);
// Make sure we actually got one
if ( $newFileName ) {
move_uploaded_file(
$_FILES["userfile"]["tmp_name"][$key],
$newFileName)
or die("Problems with upload");
}
}
}
move_uploaded_file(file, location);
You can use file and new name in location parameter like this:
$newname = "yourimg.png";
enter code here
move_uploaded_file($_FILES["userfile"]["tmp_name"][$key], "your location" . $newname);
This is the basic way of renaming, make changes to the loop for renaming both files. If you only upload 2 files at a time, you can use the array index for your logic.
You can rename a file:
Instead of below code inside foreach you have shared
move_uploaded_file(
$_FILES["userfile"]["tmp_name"][$key],
$_FILES["userfile"]["name"][$key]
) or die("Problems with upload");
You can use:
$temp = explode(".", $_FILES["userfile"]["name"]);
$newfilename = 'birthcertificate' . '.' . end($temp);
move_uploaded_file($_FILES["userfile"]["tmp_name"], $newfilename) or die("Problems with upload");
Try giving the file seperate names, in PHP you can receive them and make in one array if you need
You can also refer to this link:
How to rename uploaded file before saving it into a directory?
I'm trying to build a basic upload form to add multiple files to a folder, which is processed by PHP.
The HTML code I have is:
<form id="form" action="add-files-php.php" method="POST" enctype="multipart/form-data">
<div class="addSection">Files To Add:<br><input type="file" name="files[]" multiple /></div>
<div class="addSection"><input type="submit" name="submit" value="Add Files" /></div>
</form>
And the PHP to process is:
$file_path = "../a/files/article-files/$year/$month/";
foreach ($_FILES['files']['files'] as $file) {
move_uploaded_file($_FILES["file"]["name"],"$file_path");
}
I can run the PHP without any errors, but the files don't get added to the path folder.
Where am I going wrong with this?
I have a similar code actually in one of my projects. Try it.
foreach ($_FILES['files']['name'] as $f => $name) {
move_uploaded_file($_FILES["files"]["tmp_name"][$f], $file_path);
}
Look at the following page:
http://php.net/manual/en/function.move-uploaded-file.php
EDIT:
Nowhere in the code you provided, does it show that you actually give your file a filename, you simply refer to a path, rather than a path+filename+extension
move_uploaded_file($_FILES["files"]["tmp_name"][$f], $file_path . $name);
modifying my original code sample to be like the second one, should work.
Iterate the $_FILES['files']['error'] array and check if the files are actually uploaded to the server:
$dest_dir = "../a/files/article-files/$year/$month";
foreach ($_FILES["files"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
// The temporary filename of the file stored on the server
$tmp_name = $_FILES["files"]["tmp_name"][$key];
$name = basename($_FILES["files"]["name"][$key]);
// Handle possible failure of the move_uploaded_file() function, too!
if (! move_uploaded_file($tmp_name, "$dest_dir/$name")) {
trigger_error("Failed to move $tmp_name to $dest_dir/$name",
E_USER_WARNING);
}
} else {
// Handle upload error
trigger_error("Upload failed, key: $key, error: $error",
E_USER_WARNING);
}
}
The biggest issue with your code is that you are trying to move $_FILES['files']['name'] instead of $_FILES['files']['tmp_name']. The latter is a file name of temporary file uploaded into the temporary directory used for storing files when doing file upload.
P.S.
Using relative paths is error-prone. Consider using absolute paths with the help of a constant containing path to the project root, e.g.:
config.php
<?php
define('MY_PROJECT_ROOT', __DIR__);
upload.php
<?php
require_once '../some/path/to/project/root/config.php';
$dest_dir = MY_PROJECT_ROOT . "/a/files/article-files/$year/$month";
I have a a script that can upload the contents of a CSV file and download the links to a local directory, the CSV file i need to upload to it is about 4056 lines long and 4056 FTP downloads, the script works fine but the web server times out when i use it.
even tried set_time_limit(0);
is there a way i could session the script and loop the process so it could do it's job for a few hours without interruptions.
<?php
/**
* Please change your upload directory according to your needs. Make sure you include the trailing slash!
*
* Windows C:\tmp\
* Linux /tmp/
*/
$uploaddir = '/tmp/';
if(isset($_FILES['userfile']['name'])){
// Read uploaded file
$lines = file($_FILES['userfile']['tmp_name']);
echo "Reading file ... <br/>";
$linecount = 0;
foreach($lines as $line ){
echo ++$linecount . ". FTP Url is : " .$line . "<br/>";
echo " Downloading " . $line . "<br/>";
$parsed_url_values = parse_url($line);
//TODO perhaps do a validation of the ftp url??
if($parsed_url_values['scheme'] == 'ftp'){
// set up basic connection
$conn_id = ftp_connect($parsed_url_values['host']);
// login with username and password
$login_result = ftp_login($conn_id, $parsed_url_values['user'], $parsed_url_values['pass']);
ftp_pasv($conn_id, true);
$path = rtrim($parsed_url_values['path'], '_');
$filename = basename($path);
if (ftp_get($conn_id, $uploaddir . $filename, $path , FTP_BINARY)) {
echo " Successfully downloaded the file " .$line . "<br/>";
} else {
echo " Could not save the file to " . $line . ". Please verify the url is correct and the file exists.<br/>";
}
} else {
echo " Sorry. This script was made for FTP downloads only.";
}
}
}
?>
<form enctype="multipart/form-data" action="" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
Select the file to upload : <input name="userfile" type="file" />
<input type="submit" value="Upload" />
</form>
You need to increase the execution time of your script by using max_execution_time. You can use this example, place it on top of your script:
<?php
ini_set('max_execution_time', 300); //300 seconds = 5 minutes
.. The rest of your script
Hope this will help you!
In my practice I often use step by step loading if i can't load data via cron or php cli.
Something like that (not tested):
<?php
$newFileName = '/path/to/file.csv';
$line = isset($_REQUEST['csvline']) ? (int) $_REQUEST['csvline'] : 0;
$handle = fopen($newFileName, "r");
//10 seconds for each step
$stepTime = 10;
$startTime = time();
$lineCounter = 0;
while (($fileop = fgetcsv($handle)) !== false)
{
//already loaded lines
$lineCounter++;
if ($lineCounter <= $line) continue;
//here goes your script logic
//stops when time goes out
if (time() - $startTime >= $stepTime) break;
}
//next you need to query this script again
//using js maybe (window.location or ajax call)
//so you can see loading progress or any other useful information
//like
if (!feof($handle)) {
echo "<script>window.location = '/your.php?csvline={$lineCounter}'<script>";
}
//you even can start loading from last line before script fails
But i'm sure that using cron is the best solution for your problem.
I have a form where I allow the user to upload files. I just changed the post processing to a post-redirect-get since the user enters other information as well. I noticed that the global $_FILE is visible to the redirect.php but is lost after redirecting back to the input form. I attempted to save the $_FILE array, but it appears that the temp files are removed with the post-redirect-get. Is there any way to tell the server to preserve the temp files when leaving the redirect.php so I can process them when I see fit? Thanks in advance.
User Form:
<input type="file" name="file[]" id="userfiles" size='1px' multiple onChange="makeFileList();" />
Redirect File:
if (isset($_FILES)){
$_SESSION['post-files'] = $_FILES;
}
header("Location: /back/to/input/form.php");
In the end, the simplist solution was to process the temp files in the redirect.php and store the files in my own temp location. I then can deal with them once back in my processing form. For anyone who follows, this is what I did...
if (isset($_FILES)){
$_SESSION['post-files'] = $_FILES;
$i=0;
foreach ($_SESSION['post-files']['file']['name'] as $filename){
// get the file to upload
$fromfile=$_SESSION['post-files']['file']['tmp_name'][$i];
// get just the filename
$filename = pathinfo($fromfile, PATHINFO_FILENAME) . '.' . pathinfo ($fromfile, PATHINFO_EXTENSION);
// give it a new path
$tofile = "/some/temp/path/". $filename;
// store the new temp location
$_SESSION['post-files']['file']['tmp_name'][$i] = $tofile;
// move the files to a temp location
if (!is_dir(pathinfo($tofile,PATHINFO_DIRNAME))) {
mkdir(pathinfo($tofile,PATHINFO_DIRNAME), 0777, true);
}
move_uploaded_file($fromfile,$tofile);
}
}
You might be able to pass an encoded copy of the file(s) into the session.
Something like...
$tempImages = array();
foreach($_FILES as $file)
{
$tempImages[] = base64_encode(file_get_contents($file['tmp_name']));
}
$_SESSION['post-files'] = serialize($tempImages);
I need customers to upload files to my website and I want to gather their name or company name and attach it to the file name or create a folder on the server with that as the name so we can keep the files organized. Using PHP to upload file
PHP:>>
if(isset($_POST['submit'])){
$target = "upload/";
$file_name = $_FILES['file']['name'];
$tmp_dir = $_FILES ['file']['tmp_name'];
try{
if(!preg_match('/(jpe?g|psd|ai|eps|zip|rar|tif?f|pdf)$/i', $file_name))
{
throw new Exception("Wrong File Type");
exit;
}
move_uploaded_file($tmp_dir, $target . $file_name);
$status = true;
}
catch (Exception $e)
{
$fail = true;
}
}
Other PHPw/form:>>
<form enctype="multipart/form-data" action="" method="post">
input type="hidden" name="MAX_FILE_SIZE" value="1073741824" />
label for="file">Choose File to Upload </label> <br />input name="file" type="file" id="file" size="50" maxlength="50" /><br />
input type="submit" name="submit" value="Upload" />
php
if(isset($status)) {
$yay = "alert-success";
echo "<div class=\"$yay\">
<br/>
<h2>Thank You!</h2>
<p>File Upload Successful!</p></div>";
}
if(isset($fail)) {
$boo = "alert-error";
echo "<div class=\"$boo\">
<br/>
<h2>Sorry...</h2>
<p>There was a problem uploading the file.</p><br/><p>Please make sure that you are trying to upload a file that is less than 50mb and an acceptable file type.</p></div>";
}
Look at mkdir(), assuming the user PHP is running as has appropriate permissions, you can simply make a directory inside of uploads/.
After that, you can modify $file_name to contain some of the other posted variables that you mentioned you will add. Just take care to ensure those variables contain only expected characters.
Do your customers need to Log into your site before they upload? If that's the case perhaps you can store/grab $_SESSION information regarding their company and name. You could then append that info to the $file_name or the $target directory.
the mkdir() idea below this looks like it will probably work, but have you considered what would happen if a user entered someone else's name, had someone else's name, or entered someone else's company?
use this code on the top of the page
$path = dirname( __FILE__ );
$slash = '/';
(stristr( $path, $slash )) ? '' : $slash = '\\';
define( 'BASE_DIR', $path . $slash );
& use below code after inside if below exit;}
$folder = $file_name; // folder name
$dirPath = BASE_DIR . $folder; // folder path
$target = #mkdir( $dirPath, 0777 );
move_uploaded_file($tmp_dir, $target . $file_name);
here is your code as it is
I figured it out, I just made a input for the name ant attached it to the file name.