How to make a php request report failure - php

I'm trying to scan the files in a directory using a php request. This is my code right now:
$.ajax({
type: "POST",
url: "scandir.php",
data: { dirname: "./test" },
success: function( data ) {
console.log( data );
}
error: function() {
console.log( "error" );
}
});
scandir.php:
<?php
$dirname = $_POST[ "dirname" ];
$files = scandir( $dirname ) or die("Unable to scan directory " . $dirname );
foreach ( $files as $filename ) {
echo $filename . "\n";
}
?>
Problem is, the request always returns successfully, even if the directory "dirname" doesn't exist (it returns the text of the php directory-not-found messages). How do I make it return with an error when the directory is not found?

if(!empty($_POST["dirname"])) {
$dirname = $_POST["dirname"];
if(!is_dir($dirname)) {
header('HTTP/1.0 404 Not Found');
exit;
}
foreach(scandir($dirname) as $filename) {
echo $filename . "\n";
}
}

As you can see here, the error entry is only for http errors like timeout or 404 not found. If you want to check if the php script failed internally, you either can set a header using php's method header or you check in the success function whether the php script returned an error. Hope that helps.

Related

How to fix "getimagesize(): Read error!" in PHP

I want to upload images to a server using ajax and php.
On client-side i hava the following code:
var reader = new FileReader();
reader.readAsDataURL(file, 'UTF-8');
reader.onload = function (event) {
var result = event.target.result;
$.ajax({
type: "POST",
url: "url",
data: {
data: result,
name: file.name,
mimeType: file.type
}
});
};
On server-side my code looks like the following:
$path = 'somehow/'
$fp = fopen( $path . $_POST['name'], 'w');
$data = explode( ',', $_POST['data'] );
fwrite($fp, base64_decode( $data[ 1 ] ));
fclose($fp);
chmod($path . $_POST['name'], 7777);
list($width, $height) = getimagesize($path . $_POST['name']);
Now the method "getimagesize" always runs into an error "getimagesize(): Read error!"
Does anybody know, why this happens? When i look into the filesystem on the server the file 'FILENAME.JPG' exists ...
You can use $result = #getimagesize($file) to suppress the error.
So, when the $result is empty, means there is an error occurred.
There are two possible reasons for this error : either the url path is incommplete/incorrect or the picture file is corrupt and cannot be opened. A file may be corrupted, for example, if the image is not fully/correctly loaded onto the server.

PHP download file from server from POST

What began here: PHP finding file where post INCLUDES portion of filename
I am trying to finish with this question.
Basically, now that I am able to post a variable to a PHP process, then use that process to find a file in a directory, I now need to be able to download the file if it exists.
Quick recap, after the user has entered a voyage number and the datatable has returned a list of voyages, the user then clicks the link, which is where I'll begin the code:
$('.voyageFileCall').on('click', function()
{
var voyage = $(this).attr('data-voyage');
$.post('fileDownload.php', {voyage:voyage}, function(data)
{
// here is where I need to where either display the file doesn't exist
// or the file downloads
});
});
The process 'fileDownload.php' looks like this:
<?php
if($_POST['voyage'] == true)
{
$voyage = $_POST['voyage'];
$files = scandir("backup/");
if(count($files) > 0)
{
$fileFound = false;
foreach($files as $file)
{
if((preg_match("/\b$voyage\b/", $file) === 1))
{
// I'm guessing the download process should happen here
echo "File found: $file \n"; // <-- this is what I currently have
$fileFound = true;
}
}
if(!$fileFound) die("File $voyage doesn't exist");
}
else
{
echo "No files in backup folder";
}
}
?>
I tried to use the answer found here: Download files from server php
But I'm not exactly sure where I should put the headers, or if I need to use them at all.
The quick solution which i can suggest you is: return path to file if it is exist, and return false if file doesn't exist.
After that in your JS code you can check, if your "data" == false, you can throw an error "file doesn't exist", and if it is not "false", you can call document.location.href = data; - it will redirect your browser to the file and it will be downloaded
Why don't you simply use download attribute:
<?php
if($_POST['voyage'] == true)
{
$voyage = $_POST['voyage'];
$files = scandir("backup/");
if(count($files) > 0)
{
$fileFound = false;
foreach($files as $file)
{
if((preg_match("/\b$voyage\b/", $file) === 1))
{
// I'm guessing the download process should happen here
echo 'File found: <a href="' . $file . '" download>' . $file . '</a> \n'; // <-- this is what I currently have
$fileFound = true;
}
}
if(!$fileFound) die("File $voyage doesn't exist");
}
else
{
echo "No files in backup folder";
}
}
?>
If you really want to use JavasScript to start download then use style="display:none;" for <a> and then in JS just click it:
echo 'File found: <a id="myDownload" style="display:none;" href="' . $file . '" download>' . $file . '</a> \n';
and call it:
$('.voyageFileCall').on('click', function()
{
var voyage = $(this).attr('data-voyage');
$.post('fileDownload.php', {voyage:voyage}, function(data)
{
if(document.getElementById("myDownload")){
document.getElementById("myDownload").click();
}else{
console.log("file does not exist");
}
});
});

Parse CSV file to JSON after uploading using temporary copy

I'm almost finishing building a functionality for parsing CSV files to JSON and just need help in piecing it together. The way it works is that files will be uploaded using AJAX/Jquery. Once the files has been uploaded and sent the PHP to parse the CSV file to JSON will then execute.
After parsing, the converted file will be push or sent to the API as a JSON object. Here is the code that I have been working. For the uploading i'm using this plugin AJAX/JQuery File Uploader
This functionality is also built on using RactiveJS
AJAX/Jquery File Uploader
This is the section where I'm currently uploading or placing the file. URL is pointed at the upload.php.
<div id="fileuploader">Upload</div>
<script>
$(document).ready(function() {
$("#fileuploader").uploadFile({
url: 'upload.php',
});
})
</script>
Uploads.php
Is there a way to GET the temporary copy of the uploaded file and parse using the PHP code I have built below to convert the CSV to JSON
<?php
if ( 0 < $_FILES['file']['error'] ) {
echo 'Error' . $_FILES['file']['error'] . '<br/>';
}
else {
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
}
?>
PHP (CSV to JSON)
Right now be the file is being declared manually.
<?php
$json_data = csvToJson('lms.csv');
?>
<?php
function csvToJson($fname) {
if (!($fp = fopen($fname, 'r') )) {
die("Can't open file");
}
else {
('Upload File');
}
$key = fgetcsv($fp, "1024", ",");
$json = array();
while ($row = fgetcsv($fp, "1024", ",")) {
$json[] = array_combine($key, $row);
}
fclose($fp);
foreach ( $json as $k=>$v ) {
$json[$k]['accountName'] = $json[$k]['ACCOUNT NAME'];
$json[$k]['dateRequested'] = $json[$k]['DATE'];
unset($json[$k]['ACCOUNT NAME']);
unset($json[$k]['DATE']);
}
return json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_NUMERIC_CHECK);
}
?>
<?php // $target_file = fopen($_FILES["fileToUpload"]["tmp_name"], 'r'); ?>
Send Converted to API (Ractive/AJAX/JS)
As you can see the sending part is triggered by an on-click event (app.on)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ractive/0.9.0-build-48/ractive.js"></script>
<script type="text/javascript">
var app = new Ractive({
el : '#container',
template : '#template',
});
var proxy = 'http://192.168.1.126/lms-dev-noel/proxy.php';
var endpoint = 'account/leads/';
var rt = 'POST';
var url = proxy+'?endpoint='+endpoint+'&rt='+rt;
var lms_json = <?php echo json_encode($json_data); ?>;
var jobjects = JSON.parse(lms_json);
for ( i = 0; i < jobjects.length; i++ ) {
var data = jobjects[i];
console.log(data);
$.ajax({
type : 'POST',
url : url,
data : data,
dataType : 'json',
success : function() {
},
error : function(error) {
console.log('Error')
}
});
}
</script>
Warning and Notices
Well, it depends a bit on where that csvToJson function is located in your code. If it's within uploads.php, or in a separate file that you can include in uploads.php, then you can just do:
move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/' . $_FILES['file']['name']);
$json_data = csvToJson('uploads/' . $_FILES['file']['name']);
echo $json_data;
Then in the script, change
var lms_json = <?php echo json_encode($json_data); ?>;
to
var lms_json;
and move it to the top of your javascript.
It seems like you are trying to assign the variable before the API call has been made. Instead you need to capture the data from the the response of the uploadFile call (as per these docs: http://hayageek.com/docs/jquery-upload-file.php):
$("#fileuploader").uploadFile({
url: 'upload.php',
onSuccess:function(files,data,xhr,pd)
{
//data: response from server
lms_json = data;
}
});

Save data into file using JQuery and PHP

My problem here is even though it gets saved "successfully" the file is not actually saved. (I'm running this on the Cloud9IDE)
My folder exports is set to be readable and writable via chmod 777 -R ./.
Can someone explain to me why the hello.txt file is not being created, and what I can do to solve this problem?
JQuery:
$("[data-action=save-file]").on("click", function(e) {
var filename = "hello.txt"
var content = "Hello world!"
$.ajax({
type: "GET",
url: "submit.php",
data: {
"filename": filename,
"content": content,
},
cache: false,
success: function(msg) {
console.log(msg)
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log("Some error occurred")
}
})
})
PHP:
<?php
$filename = $_GET["filename"];
$fp = fopen("anon/".$filename, "wb");
if (!$fp) {
echo getcwd();
exit;
} else {
$outputstring = $_GET["outputstring"];
fwrite($fp, $outputstring);
}
$fclose($fp);
?>
I've also tried...
<?php
$filename = $_GET["filename"];
$outputstring = $_GET["outputstring"];
file_put_contents($filename, $outputstring, FILE_APPEND | LOCK_EX);
?>
If this is the actual code that is posted, then the arguments being sent by ajax are "content" and "filename", while php is expecting "outputstring" and "filename", so, on the php end, there is no "outputstring" and the program doesn't check for "content" in $_GET.
$filename = $_GET["filename"];
$outputstring = $_GET["content"];
file_put_contents($filename, $outputstring, FILE_APPEND | LOCK_EX);
Also there is a max length to too url parameters for GET (Max size of URL parameters in _GET), so if file content is ever an actual file this may be truncated. Try using type: "POST" instead.
maybe you should start debugging server side:
first of all, when using file_put_contents, check if it returns false (use operator ===). In this case folder anon/ doesn't exists.
second: check for writability of that folder with is_writable.
if (!isset($_GET[...], $_GET[...])) die("missing vars...");
if (!is_writable($filenamewithpath)) die("dir not writable");
if (file_put_contents(...) === false) die("dir doesn't exists");
if directory not writable, try using chmod($path, 0777). could be that your main directory is 0777 but not the sub-directories.
by the way, as others pointed out, your ajax call is sending "content", not "outputstring" as parameter. you should rename the data object key.
try also to use absolute path (using for example __DIR__ . "/anon/". $filename);
The code in php $fp.close() is error. It should be fclose($fp).
wb is not any mode in php. use w+ instead of wb
and you need to check folder is exist or not
$path = "anon";
if (!file_exists($path) && is_dir($path))
{
if (!mkdir($path, 0777, TRUE))
{
return false;
}
}

Why do I hit error in AJAX file upload with jQuery?

I am working on a multiple file uploader using HTML5's FormData and jQuery. I have the following code:
$(function() {
$('#file').bind("change", function() {
var formData = new FormData();
//loop for add $_FILES["upload"+i] to formData
for (var i = 0, len = document.getElementById('file').files.length; i < len; i++) {
formData.append("file" + i, document.getElementById('file').files[i]);
}
//send formData to server-side
$.ajax({
url : "file-upload.php",
type : 'post',
data : formData,
dataType : 'json',
async : true,
processData: false, // tell jQuery not to process the data
contentType: false, // tell jQuery not to set contentType
error : function(request) {
alert('error!!');
console.log(request.responseText);
},
success : function(json) {
alert('success!!');
$('#upload-result')[0].append(json);
}
});
});
});
I can see that my file-upload.php works fine because the files are uploaded! But why does my jQuery hit the error function and not the success function? I get an alert of Error.
In the console window, I see the result of my PHP echo call! Which I want to append to #upload-result as shown in my success function.
PHP code
foreach($_FILES as $index => $file)
{
$fileName = $file['name'];
// echo '[ file name: ' . $fileName . ' - ';
$fileTempName = $file['tmp_name'];
// echo 'file temp name: ' . $fileTempName . ' ]';
if(!empty($file['error'][$index]))
{
// some error occured with the file in index $index
// yield an error here
return false; // return false also immediately perhaps??
}
// check whether it's not empty, and whether it indeed is an uploaded file
if(!empty($fileTempName) && is_uploaded_file($fileTempName))
{
// the path to the actual uploaded file is in $_FILES[ 'file' ][ 'tmp_name' ][ $index ]
// do something with it:
move_uploaded_file($fileTempName, "uploads/" . $fileName);
echo json_encode('<p>Click here to download file!</p>');
}
}
I figured it out. I was getting the jQuery AJAX error even though my status code was 200 for the php file because I had my dataType as JSON, whilst I was returning simple HTML.
dataType: 'html',
Fixed it!
Thanks all.

Categories