I know that this should not be a difficult thing to accomplish in PHP however it is giving me the hardest time!
I am trying to do this:
1) Capture form string data AND an image upload in a single form
2) Upload both types of data to the server with a single non-ajax/traditional POST to a simple PHP script (process.php in this case)
3) Take the image the user uploaded, save it in as a text file in a directory named dynamically by the first letter of the first name and the entire last name concagnated together so for me the directory structure would be as follows: /home/uploads/nabrams/image.jpg, /home/uploads/nabrams/userdata.txt,
*The text file will contain the text strings from the client side form, the image from the input[type="file"], once again contained in the same form, sent to the server with 1 submission.
I am using a text file in order to provide the simplest case possible.
Here is the code I am working with currently:
<?php
$uploaddir = '/home/nicholasabrams/public_html' + '/newprofiledata/' + $lname + '/' + $_FILES['userfile']['name'];
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo "<p>";
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "File is valid, and was successfully uploaded.\n";
} else {
echo "Upload failed";
}
echo "</p>";
echo '<pre>';
echo 'Here is some more debugging info:';
print_r($_POST);
print_r($_FILES);
print "</pre>";
However when attempting to upload an image of several formats and sizes (multiple attempts), I am stuck at an error-less blank window. To no surprise, the script did not upload or rename the image as desired.
Also - when trying to add the post data directly into the file name like so:
$uploaddir = '/home/nicholasabrams/public_html/' + $_POST['lname'] + '/' + $_FILES['userfile']['name']; $uploadfile = $uploaddir . basename($_FILES['userfile']['name']); if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile))...
I get filenames with 0pictureNameHere.jpg instead of NAbrams.jpg or if using post data to set the directory, I will never get the image or data in this way.
Side note:
I am a Javascript and jQuery ( <- mainly) developer, would it be worth it for me to attempt doing this with express or some other node module? I am not experienced with node although I have been "using it" for the last few months.
Thanks for the help!
Related
I have developed a neural network model with tensorflow. I want to save weights of my model on each time they update. So i though of updating a file on the server every time it learns. but the documentation on tensorflow js website on saving model using http server is really confusing. So i did some research and found some code. Still it is not working. I know i am missing the "multipart/form-data" and fact that there are two files, "The body consist of two files, with filenames model.json and model.weights.bin". Could not find anything that could help me. link to tensorflow documentation!
javascript to save
model.save('http://example.com/save.php');
save.php
<?php
$putdata = fopen("php://input", "r");
$fname = "weights.json";
$file = fopen("../static/" .$fname, 'w');
while ($data = fread($putdata, 1024)){
fwrite($file, $data);
}
fclose($file);
fclose($putdata);
?>
http://php.net/manual/en/function.file-put-contents.php
I don't see the input section with php stdin. This makes me feel like the connection isn't sending a stream like a socket connection, but rather a standard HTTP payload with a body attribute. But wait, theirs caveats. If it is a JSON payload you'll need the second two lines (like you had in your code, but not as a resource). The first two are my guess as to what may be going on. Remember you can debug through your browsers console to see the data payload, request method, ect...
$data = '<pre>' . json_encode($_POST) . '</pre>';
file_put_contents('stdPost.html', $data);
$data = file_get_contents('php://input');
file_put_contents('stdInput.json', $data);
I have an issue.
I have an index.php with several checkboxes.
Every checkbox represents a piece of code.
I am trying to create some generating tool.
For example: if I select four checkboxes, I want that four specific parts of code to generate in one php file, then zip it and download on my computer.
I know I can do it something like this:
$files = array('list.php', 'one-image.php', 'gallery.php', 'pdf.php');
$zipname = 'file.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
but, at the moment i am pretty lost.
Thanks in advance.
Copied from comments:
Read the files yourself using file_get_contents, concatenate using +, write to zip with ZipArchive::addFromString.
How can I store text from a site to a local file?
So basically the script needs to do the following:
go to this site (fake site)
http://website/webtv/secure?url=http://streamserver.net/channel/channel.m3u8**&TIMESTAMP**
where TIMESTAMP can be a timestamp to make it unique.
the site will respond with:
{
"url":"http://streamserver.net/channel/channel.m3u8?st=8frnWMzvuN209i-JaQ1iXA\u0026e=1451001462",
"alternateUrl":"",
"Ip":"IPADRESS"
}
Grab the url and convert the text as follows:
http://streamserver.net/channel/channel.m3u8?st=8frnWMzvuN209i-JaQ1iXA\u0026e=1451001462
must be:
http://streamserver.net/channel/channel.m3u8?st=8frnWMzvuN209i-JaQ1iXA&e=1451001462
so \u0026e is replaced by &
and store this text in a local m3u8 file.
I am looking for a script either php or any other code is welcome which can perform this. Any help is appreciated.
I tried a small script just to show the contents but then I get the error:
Failed to open stream: HTTP request Failed!
It seems that php tries to open it as a stream instead of a website. It should see it as a site because only then the response is sent.
<?php
$url = 'http://website/webtv/secure?url=http://streamserver.net/channel/channel.m3u8&1';
$output = file_get_contents($url);
echo $output;
?>
This is not a tutorial website, so I am not going to provide you more details. You can try the following code:
<?php
$json_url = "http://linktoyour.site"; //change the url to your needs
$data = file_get_contents($json_url); //Get the content from url
$json = json_decode($data, true); //Decodes string to JSON Object
$data_to_save=$json["url"]; //Change url to whatever key you want value of
$file = 'm3u8.txt'; //Change File name to your desire
file_put_contents($file, $data_to_save); //Writes to File
?>
I think there is issue with your PHP configuration.
It like as allow_url_fopen is denied.
See more http://php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen
For some reason, when I try to send JSON data to a PHP page (where it gets downloaded as a spreadsheet), it runs without error, but doesn't bring up the prompt to download the spreadsheet. The JSON has generated without problem (I have made the PHP page create the file on the server, before trying to make it download without creating it).
Here is the JavaScript code that sends the JSON data to the server:
function writeToSpreadsheet()
{
// get the json for #theTable
var tableJSON = tableToJSON("tr:not(#titleRow)");
//alert(tableJSON);
alert("Sending table data to be written to the spreadsheet...");
$.post('/ResearchProject/tableContent/exportTable.php', {'table': tableJSON}).done(
function(response) { alert(((response == '') ? response : (tableJSON.title + ' written to file!')));})
.fail(function (xhr, ajaxOptions, thrownError) { alert("ERROR:" + xhr.responseText+" - "+thrownError); });
}
and here is exportTable.php
<?php
function cleanData(&$str)
{
$str = preg_replace("/\t/", "\\t", $str); // escaping all of the tabs
$str = preg_replace("/\r?\n/", "\\n", $str); // escaping any and all cases of carriage return
// if there is a single double-quote in the string, we wrap the string in quotes, replace every single double-quote with double double-quotes, and
// end with a double-quote
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// the data is coming from a JSON object that is being sent here
if (isset($_POST['table']))
{
$tableJSON = $_POST['table']; # somehow, this is already a PHP array (exactly the one we need)!!
// get the name of the table from the $tableJSON
$tableName = $tableJSON['title'];
// get the title row from $tableJSON
$titleRow = $tableJSON['titleRow'];
// fix the titleRow
foreach ($titleRow as $heading)
{
$heading = trim(preg_replace('/\s+/', ' ', $heading));
}
// get the rows from $tableJSON
$rows = $tableJSON['rows'];
// form the filename from the tableName
$fileName = $tableName . '.xls';
// here, we download the file without even creating it
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Content-Type: application/vnd.ms-excel");
// we echo the titleRow first
array_walk($titleRow, 'cleanData');
echo implode(chr(9), $titleRow) . "\r\n";
?>
<script>console.log('Title row written to file.');</script>
<?php
// now we echo the data
foreach($rows as $row)
{
array_walk($row, 'cleanData');
echo implode(chr(9), $row) . "\r\n";
?>
<script>console.log('Data row written to file.');</script>
<?php
}
}
else
{
echo 'You sent me no data :(\n';
}
?>
OK, MikeWarren, how do I test this??
You can test it by selecting a table from the dropdown menu and clicking the "Export table to spreadsheet" button here: http://dinotator.biokdd.org/ResearchProject/tableViewer.php
I am trying to have it where the table that is on the HTML page gets converted into an JSON object, and then downloaded. Thus, I would need to POST the data to the PHP page, right? (Query strings don't work.)
Query strings won't work because you are using jQuery's $.post call which means that your data is sent in the body of the request, as opposed to a query string which is what a GET uses. For JSON you do indeed want to use a POST.
As for what's going wrong, you need to decode your JSON into a PHP array using json_decode. Unfortunately it can't simply handle JSON how it is.
So most likely you'll want to do:
// now a poorly named variable
$tableJSON = json_decode($_POST['table']);
Also, looking at your Ajax, $.post does accept a .fail() listener, but it doesn't pass any error data as part of the callback. So if you want to be able to handle incoming response errors you'll need to use $.ajax:
$.ajax({
type: "POST",
url: "/your/url.php",
dataType: "json",
error: errorCallback
});
Finally, looking at how your code is structured, if you're actually trying to save to file, you're going to need some more logic. Right now, you're just rendering that table, and then returning it as a response which will show up in your done function. You're going to add some more logic in order to make it actually download. This question entails your exact problem.
Good luck!
I have found so much bad advice on the internet about how to solve this problem. One of the answers here also didn't work. :(
I have decided to get advice from a friend of mine, and me and him have decided on this approach:
Have my exportData.php simply write the data to $_SESSION, echo a JSON-encoded "success", and then exit
On exit, on the client-side of things, if "success" has been received, have the JavaScript open up a new tab to a file that I have created called downloadFile.php which actually does the downloading.
Why didn't sending the data between files work?
Downloading data entails setting the right headers and printing the data. When you send data to the file to do this (via AJAX), the buffer that the data is printed to is the one for response. You can see this by saying something like
success: function(response)
{
alert(response);
} and see the data that you "downloaded" not get downloaded, but get printed on-screen.
However, if you go to the file instead of simply passing data to it, your data will download, provided that it has access to the data that you are trying to download. You can see examples of this here: www.the-art-of-web.com/php/dataexport/ . In those examples, the data was "static" (that is, only existing in the scope of that PHP file, until download happened).
We then see that we should let another file handle the downloading. Here is what its contents should look like:
<?php
if (!isset($_SESSION))
session_start();
function cleanData(&$str)
{
$str = preg_replace("/\t/", "\\t", $str); // escaping all of the tabs
$str = preg_replace("/\r?\n/", "\\n", $str); // escaping any and all cases of carriage return
// if there is a single double-quote in the string, we wrap the string in quotes, replace every single double-quote with double double-quotes, and
// end with a double-quote
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}
// get the data from $_SESSION
if (isset($_SESSION))
{
$fileName = $_SESSION['fileName'];
$titleRow = $_SESSION['titleRow'];
$rows = $_SESSION['rows'];
// set the excel headers
header("Content-Type: application/vnd.ms-excel");
//header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$fileName\"");
header("Pragma: no-cache");
header("Expires: 0");
// attempt download
array_walk($titleRow, 'cleanData');
echo implode(chr(9), $titleRow) . "\r\n";
// now we echo the data
foreach($rows as $row)
{
array_walk($row, 'cleanData');
echo implode(chr(9), $row) . "\r\n";
}
}
else
{
die('Problem with session variable. Data could not be sent for download.');
}
exit;
?>
Of course, before doing this, make sure that you have 'fileName', 'titleRow', and 'rows' already written to $_SESSION.
This should help anyone having problem downloading HTML table to Excel spreadsheet via PHP, and the best part is that you don't have to bloat your server by downloading an entire library, for potentially the functionality of one button!!
I am creating an application that allows a user to attach a file, type a message, then an email is sent using the PHP mailer plugin for wordpress. I use javascript to get the file information from the upload html form and then php to send the email. The plugin works when sending a file that is saved on the server in a specific location using this function:
$mail->AddAttachment("./new6.txt","attachment");
I was wondering if there is a way to email the file selected without having to save it to the server. In other words, can a user select a file to upload, but send the file with this php function without saving it in a location to be retrieved? I know there is a $_FILES array that you can get the file's information but will that file be able to be sent without it being saved somewhere first? I'm guessing not since the whole point of the upload form is to "upload" it but just wondering if something could be done in javascript or something.
Thanks for any help
You can't truly do that, but you could do this to get a close effect:
$filename = $_FILES['file_name']['tmp_name'];
$main->AddAttachment($filename, "attachment");
// Send the email... then:
unset($filename);
This adds the file as an attachment, sends the email, then deletes the file. The uploaded files in the $_FILES array will automatically be flushed out eventually, so I'm not sure if the unset() part even does anything significant, but it surely gets rid of the file.
Without Saving file in Server, you can not attach it for mail.
1> Mailing function is executing in Server.
2> It is not possible from Server to get the absolute file path in client machine as in web, the client machines do not have any absolute address.
3> So the file is needed to be uploaded in server to get a real path for the file to have in attachment of Mail.
I know this is a rather old question, but I think there's a rather useful answer that was never given. For the sake of those like me who happned along this question while searching for an answer to this question or similar, here you go.
When you upload a file to a server from a form, it's saved to the tmp directory automatically. Technically it's impossible to do anything with a form uploaded file without saving, because it's done for you automatically. However, because tmp is automatically cleaned on every reboot, this shouldn't be an issue in terms of building up too much backlog, if you either reboot often or set up a cron to delete your tmp directories contents regularly.
However, because it's saved to tmp, and because you can manipulate the file from there, it is possible to send the file without saving it for any form of longevity, and without actually writting anything to save it. Provided you perform all the necessary security checks on the file (verifying the contents, MIME-type and such that I won't go into now, but you can read up on how to do here), you can use the following php function which I got from Codexworld and modified to use the tmp files. All you need to do is pass
the parameters, and the $files is an array of files you've hopefully already vetted.
function multi_attach_mail($to, $subject, $message, $senderEmail, $senderName, $files = array()){
$from = $senderName." <".$senderEmail.">";
$headers = "From: $from";
// Boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// Headers for attachment
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
// Multipart boundary
$message = "--{$mime_boundary}\n" . "Content-Type: text/html; charset=\"UTF-8\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
// Preparing attachment
if(!empty($files)){
for($i=0; $i<count($files); $i++){
if(is_file($files[$i]["tmp_name"])){
$tmp_name = basename($files[$i]["tmp_name"]);
$file_name = $files[$i]["name"];
$file_size = filesize($files[$i]["tmp_name"]);
$message .= "--{$mime_boundary}\n";
$fp = fopen($files[$i]["tmp_name"], "rb");
$data = fread($fp, $file_size);
fclose($fp);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: application/octet-stream; name=\"".$file_name."\"\n" .
"Content-Description: ".$file_name."\n" .
"Content-Disposition: attachment;\n" . " filename=\"".$file_name."\"; size=".$file_size.";\n" .
"Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
}
}
}
$message .= "--{$mime_boundary}--";
$returnpath = "-f" . $senderEmail;
// Send email
$mail = mail($to, $subject, $message, $headers, $returnpath);
// Return true, if email sent, otherwise return false
if($mail){
return true;
}else{
return false;
}
}