I'm testing uploads on 3 files on my desktop test.xlsx, test - Copy.xlsx, and test - Copy (2).xlsx. My PHP script is breaking at the line where my move_uploaded_files statement is. I get the error move_uploaded_file(uploads/test - Copy.xlsx): failed to open stream: No such file or directory. BUT test - Copy (2).xlsx is uploaded when I check my uploads folder. My PHP is as follows:
foreach($_FILES['file']['name'] as $key=>$value){
$fileName = $_FILES['file']['name'][$key];
$fileTmpLoc = $_FILES['file']['tmp_name'][$key];
$fileErrorMsg = $_FILES['file']['error'][$key];
$type = $_FILES['file']['type'][$key];
if(){
//validation
} else{ //if validated
if(move_uploaded_file($fileTmpLoc, 'uploads/'.$fileName)){
//do more stuff
} else{
echo "Upload failed.";
}
}
}
The //do more stuff actually runs once for test - Copy (2).xlsx (the only file uploaded successfully). My JS script is below but I doubt that's the part that's breaking since when I print_r($_FILES) in PHP, all files appear in the output.
var upload = function(event){
var file = document.getElementById('file').files;
var data = new FormData();
for (i=0; i<file.length; i++){
data.append('file[]', file[i]);
}
var request = new XMLHttpRequest();
request.addEventListener('load', completeHandler, false);
request.addEventListener('error', errorHandler, false);
request.addEventListener('abort', abortHandler, false);
request.open('POST', 'php/excel_upload_read.php');
request.send(data);
};
What am I doing wrong?
Looks like you are using the multi-dimensional array in the wrong order. Try this:
foreach($_FILES['file'] as $key=>$value){
$fileName = $_FILES['file'][$key]['name'];
$fileTmpLoc = $_FILES['file'][$key]['tmp_name'];
$fileErrorMsg = $_FILES['file'][$key]['error'];
$type = $_FILES['file'][$key]['type'];
...
}
The problem is the way $_FILES global is structured, it does not let you iterate easily.
You can use this function it s meant to reorganize the data structure
function reArrayFiles(&$file_post) {
$file_ary = array();
$file_count = count($file_post['name']);
$file_keys = array_keys($file_post);
for ($i=0; $i<$file_count; $i++) {
foreach ($file_keys as $key) {
$file_ary[$i][$key] = $file_post[$key][$i];
}
}
return $file_ary;
}
Then you can use foreach easily:
if(isset($_FILES['file']['tmp_name'], $_POST)) {
$files = reArrayFiles($_FILES['file']);
foreach ($files as $file) {
$temp = $file['tmp_name'];
$path = 'uploads/'.$file['name'];
if(move_uploaded_file($temp, $path)){
echo 'Upload succesful';
}else{
echo 'failed to upload';
}
}
}else{
echo 'file not uploaded';
}
This function reArrayFiles was posted by someone in the PHP documentation:
http://php.net/manual/en/features.file-upload.multiple.php
Related
I need to get an array $data from the backend to the frontend in order to organize it for viewing. I can only find examples using jQuery Ajax.
<!DOCTYPE html>
<html>
<style>
.table_class{
display:none;
}
</style>
<script>
async function uploadFile() {
let formData = new FormData();
formData.append("file", fileupload.files[0]);
console.log(formData);
await fetch('file_ingest.php', {
method: "POST",
body: formData,
});
var test = document.getElementById("test");
test.innerText = ('The file has been uploaded successfully.');
//var returned_vals = JSON.parse(formData.responseText);
//console.log(returned_vals);
}
</script>
<body>
<input id="fileupload" type="file" name="fileupload" />
<button id="upload-button" onclick="uploadFile()"> Upload </button>
<p id = "test"></p>
</body>
</html>
I need to get an array $data from the backend to the frontend in order to organize it for viewing. I can only find examples using jQuery Ajax.
<?php
set_time_limit(120);
/* Get the name of the uploaded file */
$filename = $_FILES['file']['name'];
/* Choose where to save the uploaded file */
$location = "uploads/".$filename;
if ( move_uploaded_file($_FILES['file']['tmp_name'], $location) ) {
echo 'Success';
} else {
echo 'Failure';
$CSVfp = fopen("uploads/${filename}", "r");
if($CSVfp !== FALSE) {
while(! feoF($CSVfp)) {
$data = fgetcsv ($CSVfp, 1000, ",");
print json_encode($data);
//echo $data;
}
}
fclose($CSVfp);
<?php
set_time_limit(120); // if you need this you may have other problems
/* Get the name of the uploaded file */
$filename = $_FILES['file']['name'];
/* Choose where to save the uploaded file */
$location = "uploads/".$filename;
$response = [];
/* Save the uploaded file to the local filesystem */
if ( move_uploaded_file($_FILES['file']['tmp_name'], $location) ) {
$response['status'] = 'Files Save Success';
// read the file here, if it failed the upload and move
// there is no point trying to read it
if (($fp = fopen($location, "r")) !== FALSE) {
while (($data = fgetcsv($fp, 1000, ",")) !== FALSE) {
$response['data'][] = $data
}
fclose($fp);
}
} else {
$response['status'] = 'File Save Failure';
}
// now you can return either an error or a success and data
echo json_encode($response);
Now you need to checnge the javascript to look for the status in the right place and unload the row data from the the right place
I am making a javascript XMLHttpRequest() request to execute some php in the background. Now I know the callback will only receive the first response from php. How can I get output to send back what php is echoing as it is happening to show it on the main page as php is running in the background?
javascript
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var phpResponse = this.responseText
// i know this will only be the first thing echoed by php
}
};
xhttp.open("GET", "scan.php?scanRoot=yes", true);
xhttp.send();
php run in the back ground
function rootDirFileSort($scanDir,$getID3){
//Sort stray files in root directory. Put them in a dir named by artist
$printFix = str_repeat(" ", 8157);
$files = array_diff(scandir($scanDir), array('.', '..'));
//Get files in dir. Only get flac and mp3 files
$FilesArray = array_diff(scandir($scanDir), array('.', '..'));
$FilesArray = preg_grep('~\.(flac|mp3)$~', $FilesArray);
$files = array_values($FilesArray);
foreach ($files as $file){
$file_Basename = basename($file);
// Get the metadata from file. Returns as an array
$metaDataArray = $getID3->analyze($scanDir.$file);
//Check for ID3v1 metadata container
if (isset($metaDataArray['tags']['id3v1']['artist'][0])){
$artist = $metaDataArray['tags']['id3v1']['artist'][0];
$artist = str_replace(array('.',',','?','/','\\','$'), array('','','','','',''), ucwords($artist));
}else{
$artist = '';
}
//Check for vorbis comment metadata container
if(isset($metaDataArray['tags']['vorbiscomment']['artist'][0])){
$artist = $metaDataArray['tags']['vorbiscomment']['artist'][0]; echo $artist;
$artist = str_replace(array('.',',','?','/','\\','$'), array('','','','','',''), ucwords($artist));
}else{
$artist = '';
}
//If the artist meta tag is present move the file
if(!empty($artist)){
//Check if diretory exists before making one
if(!is_dir($scanDir.$artist)){
//If file DOES NOT exist
mkdir($scanDir.$artist, 0755, true);
rename($scanDir.$file, $scanDir.$artist.'\\'.$file);
echo $file.'<br>'.$artist.'<br>Moved To: '.$scanDir.$artist.'\\'.$file.'<br><br>'.$printFix;
}else{
//If file exists
rename($scanDir.$file, $scanDir.$artist.'\\'.$file);
echo $file.'<br>'.$artist.'<br>Moved To: '.$scanDir.$artist.'\\'.$file.'<br><br>'.$printFix;
}
}else{
//Put failures in an array to show which failed when done
$notProcessed[] = array('musicFile'=>$file_Basename);
}
}
//Show all the failures if they exist
if(count($notProcessed) >= 1){
echo '<strong>***** These items failed as they don\'t contain ID3v1, ID3v2 or Vorbis Comment meta container. Manually process directories. *****</strong><br><br>';
foreach($notProcessed as $value){
echo '<strong>File:</strong> '.$value['musicFile'].'<br><br>'.$printFix;
}
}
echo '<br><br>------------------------- Root File Scan Finished! -------------------------'.$printFix;
}
<?php
include 'model.php';
$rs=new database();
if(isset($_POST["Import"])){
echo $filename=$_FILES["file"]["tmp_name"];
if($_FILES["file"]["size"] > 0)
{
$file = fopen($filename, "r");
while (($emapData = fgetcsv($file, 10000, ",")) !== FALSE)
{
$res=$rs->insert($emapData[0],$emapData[1],$emapData[2],$emapData[3],$emapData[4],$emapData[5]);
$result=mysql_fetch_array($res);
if(! $result )
{
echo "<script type=\"text/javascript\">
alert(\"Invalid File:Please Upload CSV File.\");
window.location = \"result.php?msg=valid\"
</script>";
}
}
fclose($file);
echo "<script type=\"text/javascript\">
alert(\"CSV File has been successfully Imported.\");
window.location = \"result.php?msg=valid\"
</script>";
mysql_close($conn);
}
}
?>
this code only uploads csv file but i want to upload xls too with this code. if possible i want to upload all format of excel . and the rest of code is working fine and also i dont want to change the method.
Download PHPExcel
https://github.com/PHPOffice/PHPExcel
and create this function
function getDataFromExcel($filename)
{
$excel = PHPExcel_IOFactory::load($filename);
$sheet = $excel->getSheet(0);
$highestRow = $sheet->getHighestRow();
$sheetData = $sheet->toArray(null, true, true, true);
return $sheetData;
}
It will return data in array
if you want to know the type of file use this method
function getFileType($key)
{
//Define type
$type = 'unknow';
if(isset($_FILES[$key])) {
$file = $_FILES[$key];
$fileType = $file['type'];
if (strrpos($fileType, 'csv')) {
$type = 'csv';
} else if (($fileType == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') || ($fileType == 'application/vnd.ms-excel')) {
$type = 'excel';
}
}
return $type;
}
I want a progressbar to be shown while a video-file is being uploaded. I'm using JS and AJAX to track progress of the file-upload php, and send the file. The php file contains a ffmpeg command that grabs some frames from the video. Essentially the php file creates a random folder, and puts both the video and the frames in it. when the php is called by if(isset($_FILES['file'])) it works just fine. But when i try to use AJAX it only uploads the video, but ignores the ffmpeg command and mysql_query.
Javascript:
function uploadFile(){
var file = _("file1").files[0];
var formdata = new FormData();
formdata.append("file1", file);
var ajax = new XMLHttpRequest();
ajax.upload.addEventListener("progress", progressHandler, false);
ajax.open("POST", "upload.php");
ajax.send(formdata);
Upload.php
$name = $_FILES['file1']['name'];
$type = explode(".",$name);
$type = end($type);
$tmp = $_FILES['file1']['tmp_name'];
$uploadOk = 1;
$exp = explode(".",$name);
$filename = rand().$exp[0];
$path = "videos/" . $filename . "/" . $name;
$ffmpeg = "/usr/local/bin/ffmpeg";
$size = "320x180";
if($type != 'mp4' && $type != 'MP4'){
$message = "Only mp4 format is supported!";
$uploadOk = 0;
}else{
mkdir("videos/".$filename);
// ffmpeg function
for($num = 1; $num <= 15; $num++){
$interval = $num * 3;
shell_exec("$ffmpeg -i $tmp -an -ss $interval -s $size /videos/$filename/thumb$num.png");}
move_uploaded_file($tmp, $path);
mysql_query("INSERT INTO table (name, url) VALUES('$name', '$path')");
Why dosen't AJAX execute the complete php?
So, I looked up a tutorial for uploading and sending files to a server with an XML HTTP Request. I followed the tutorial, however, I think I must be missing something. While the file appears to be uploaded and sent, nothing in the "handler" file is ever accessed. Is there a PHP function I need to write to process it? For context, here is what I wrote:
$(document).ready(function()
{
$('#upload-button').click(function(event)
{
$('#upload-button').removeClass("btn-danger");
});
$( "#report-form" ).submit(function( event )
{
var form = document.getElementById('report-form');
var fileSelect = document.getElementById('file-select');
var uploadButton = document.getElementById('upload-button');
event.preventDefault(); // Stop the event from sending the way it usually does.
uploadButton.value = 'Submitting...'; // Change text.
var files = fileSelect.files;
var maxfiles = <?php echo $config['Report_MaxFiles'] ?>;
var mfs = <?php echo $config['Report_MaxFileSize'] ?>;
if(files.length > maxfiles) // Make sure it's not uploading too many.
{
uploadButton.value = 'You uploaded too many files. The limit is ' + maxfiles + '.'; // Update button text.
$('#upload-button').addClass('btn-danger'); // Make the button red, if so.
return;
}
var formData = new FormData(); // Make a "form data" variable.
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Add the file to the request.
if(file.size / 1000 > mfs)
{
uploadButton.value = 'One of the files is too big. The file size limit is ' + (mfs) + 'kb (' + (mfs / 1000) + 'mb).';
$('#upload-button').addClass('btn-danger');
return;
}
formData.append('files[]', file, file.name); // Not really sure what this does, to be honest,
// but I think it makes a file array.
}
var xhr = new XMLHttpRequest(); // Construct an XML HTTP Request
xhr.open('POST', 'assets/class/FileHandler.php', true); // Open a connection with my handler PHP file.
xhr.onload = function ()
{
if (xhr.status === 200)
{
uploadButton.value = 'Files Submitted!'; // NOTE: I do get this message.
}
else
{
uploadButton.value = 'An error occurred.';
$('#upload-button').addClass("btn-danger");
}
};
xhr.send(formData); // I think this is where it dies.
});
});
At the "send(formData)" line, I'm not actually sure if it's sending. Do I set up some sort of listener in FileHandler.php that is activated when the files are sent via XML HTTP request? Or more specifically, how to I save the uploaded files to the server using my FileHandler.php file?
EDIT: I haven't been able to come up with any other PHP code in the FileHandler.php file than this, which I thought might be called when the form is sent (but it isn't):
EDIT 2: Okay, now I have something, but it isn't working (didn't expect it to). I think I may be using the variables wrong:
<?php
$uploaddir = 'data/reports/uploads/' . $_POST['id'] . "/";
$uploadfile = $uploaddir . basename($_FILES['files']['name']);
echo "<script>console.log('RECEIVED');</script>";
echo '<pre>';
if (move_uploaded_file($_FILES['files']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print_r($_FILES);
print "</pre>";
It's not saving the file to the directory, nor is it printing the script message. How do I get my report.php file to execute these things in FileHandler.php?
Thanks to the help and patience of #Florian Lefèvre, I got it fixed. :)
The problem was with the path. It wasn't locating the path to the folder data/uploads/ and wasn't making the directory. Here is what I did:
$uploaddir = '../../data/reports/uploads/' . $_POST['id'] . "/";
echo "NAME: " . $_FILES['files']['name'][0] . "\n";
foreach($_FILES['files']['name'] as $filenumber => $filename)
{
$uploadfile = $uploaddir . basename ($filename);
echo "UploadDir " . $uploaddir . "\n";
echo "UploadFile " . $uploadfile . "\n";
echo '<pre>';
echo "MKDir for UploadDir which is: ". $uploaddir . "\n";
mkdir ($uploaddir);
if (move_uploaded_file ($_FILES['files']['tmp_name'][$filenumber], $uploadfile))
{
echo "File is valid, and was successfully uploaded.\n";
}
else
{
echo "Possible file upload attack!\n";
}
echo 'Here is some more debugging info:';
print "</pre>";
}
var_dump ($_FILES);
I haven't gotten rid of some of the debug stuff yet, but that's the general solution.