php - List contents of a directory in HTML form dropdown and button to move selected file into a different directory
I am trying do two things.
- Build a HTML form dropdown that lists the files in a specific directory.
- On submit of a selected file from the dropdown list move the selected file from its current location to a new directory.
So far I have the following HTML/PHP for the dropdown:
</div>
<div class="u-form u-form-1">
<form action="end.php" method="POST" class="u-clearfix u-form-spacing-25 u-form-vertical u-inner-form" source="email" name="End" style="padding: 10px;">
<div class="u-form-group u-form-select u-form-group-1">
<label for="select-7512" class="u-custom-font u-heading-font u-label u-label-1">Select File</label>
<div class="u-form-select-wrapper">
<select id="select-7512" name="end" class="u-border-1 u-border-custom-color-1 u-custom-font u-heading-font u-input u-input-rectangle u-radius-50 u-white u-input-1" required="required">
<?php
$path = "/usr/local/data/";
$show = array( '.conf' );
$file_matcher = realpath(dirname(__FILE__)) . '/usr/local/data/*.{conf}';
foreach( glob($file_matcher, GLOB_BRACE) as $file ) {
$file_name = basename($file);
$select .= "<option value='$file'>$file_name</option>\n";
}
echo "$select";
?>
</select>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="12" version="1" class="u-caret"><path fill="currentColor" d="M4 8L0 4h8z"></path></svg>
</div>
</div>
<div class="u-align-left u-form-group u-form-submit">
<a href="#" class="u-btn u-btn-round u-btn-submit u-button-style u-custom-color-2 u-custom-font u-heading-font u-radius-50 u-btn-1">End<br>
This is getting me a dropdown menu but it does not list any of the files in the /usr/local/data/
directory. I have checked and the permissions to this directory are okay. I believe my code must be wrong.
Once a file has been selected from the dropdown list I would like the submit button to run a PHP script that will move the selected file from its current dir /usr/local/data/
to /usr/local/archive/
maintaining its filename. I am not so familiar with PHP so I believe my script is probably majorly wrong here but I was building something like this:
<?php
$filePath = '/usr/local/data/';
$destinationFilePath = '/isr/local/archive/';
rename($source_file, $destination_path . pathinfo($source_file, PATHINFO_BASENAME));
}
else {
echo "The file has been moved";
}
?>
Apologies in advance for any glaring problems but could someone please help me as to where I am going wrong with both steps here. Thanks for any guidance!
UPDATE
<?php
# the pattern for file matching by file extension
$pttn='@(\.conf)$@i';
# the folder to scan /path/to/directory ~ ie: /usr/local/data/
$path="/usr/local/data/";
# find the files using glob and file match using preg_grep
$files=preg_grep( $pttn, glob( $path . '/*.*' ) );
# process file found that match the pattern and build the select menu
echo '<select name="end">';
foreach( $files as $filepath )printf('<option value="%s">%s', realpath( $filepath ), pathinfo( basename( $filepath ),PATHINFO_FILENAME) );
echo '</select>
<!--
handle the user selection from dropdown menu...
-->
<script>
document.querySelector("select[name='end']").addEventListener("change",function(e){
if( this.options.selectedIndex > 0 ){
let fd=new FormData();
fd.set("filepath", this.value );
fetch( "archivefile.php", { method:"post", body:fd } )
.then( r=>r.text() )
.then( text=>{
this.removeChild( this.options[ this.options.selectedIndex ] );
alert( text )
})
}
})
</script>';
file archive script
<?php
if( isset( $_POST['filepath'] ) ){
$source = realpath( $_POST['filepath'] );
$targetdir = sprintf( '%s/usr/local/archive', __DIR__ );
$destination = sprintf( '%s/%s', $targetdir, basename( $source ) );
if( !file_exists( $targetdir ) )mkdir( $targetdir, 0777, true );
clearstatcache();
if( $source && file_exists( $source ) ){
$status=rename( $source, $destination );
}
clearstatcache();
exit( $status ? 'Success ' : 'Failure.' );
}
?>
Answer
Solution:
The filepath you cite in the question is a *nix type path and I have no means by which to test this script as it is written on a windoze system so the path variable might need tweaking?!
The following scans the current working directory ( __DIR__
) and lists the .conf
or .config
files found therein - should be simple enough to use your path and possibly tweak the regex pattern if you need more filetypes added.
# the pattern for file matching by file extension
$pttn='@(\.conf|\.config)$@i';
# the folder to scan /path/to/directory ~ ie: /usr/local/data/
$path=__DIR__;
# find the files using glob and file match using preg_grep
$files=preg_grep( $pttn, glob( $path . '/*.*' ) );
# process file found that match the pattern and build the select menu
echo '<select name="end">';
foreach( $files as $filepath )printf('<option value="%s">%s', realpath( $filepath ), pathinfo( basename( $filepath ),PATHINFO_FILENAME) );
echo '</select>
<!--
handle the user selection from dropdown menu...
-->
<script>
document.querySelector("select[name=\'end\']").addEventListener("change",function(e){
alert( this.value )
})
</script>';
updates
The Javascript I would modify like this so that it fires off an AJAX request to whatever backend script determined to be the upload/move handler.
document.querySelector("select[name='end']").addEventListener("change",function(e){
if( this.options.selectedIndex > 0 ){
let fd=new FormData();
fd.set("filepath", this.value );
fetch( "file-move-target.php", { method:"post", body:fd } )
.then( r=>r.text() )
.then( text=>{
this.removeChild( this.options[ this.options.selectedIndex ] );
alert( text )
})
}
})
And the endpoint to handle the file move:
<?php
if( isset( $_POST['filepath'] ) ){
$status=false;
$source = realpath( $_POST['filepath'] );
$targetdir = sprintf( '%s/usr/local/archive', '' );
$destination = sprintf( '%s/%s', $targetdir, basename( $source ) );
if( !file_exists( $targetdir ) )mkdir( $targetdir, 0777, true );
clearstatcache();
if( $source && file_exists( $source ) ){
$status=rename( $source, $destination );
}
clearstatcache();
exit( $status ? 'File moved' : 'Error: unable to move file' );
}
?>
Source