I am trying to create a zip folder on the fly. The zip will hold images that a user has selected from a library that is hosted on Amazon S3. Below is the code I have so far.
REQUEST URL FROM POST
function download_multi() {
//$user_id, $files, $project_id, $project_name
$this->load->library('aws');
$user = User::get_user();
$requestedHashes = $this->input->post("files");
$files = array();
foreach($requestedHashes as $hash) {
$files[] = hex_to_string($hash);
}
$project_id = $this->input->post("projectid");
$project = new Project($project_id);
$project_name = $project->project_name;
$this->aws->create_zip($user->id, $files, $project_id, $project_name, (int)$this->input->post("downloadToken"));
}
Create Zip
public function create_zip($user_id, $files, $project_id, $project_name, $cookie) {
//create a random folder name to avoid collision.
$this->folder = md5(time() . rand());
if(!mkdir('./files' . '/' . $this->folder, 0777, TRUE)) {
exit("Folder not created\n");
}
//create zipfile
$this->filename = $this->local_file_path . $this->folder . '/files.zip';
$zip = new ZipArchive();
if ($zip->open($this->filename, ZIPARCHIVE::CREATE) !== TRUE) {
exit("cannot open <$this->filename>\n");
}
//create options for downloading each file to the server
//temporarily to add to archive
$opt = array('preauth' => '+1 minutes');
//download each file to the server.
foreach ($files as $file) {
//generate a link.
$response = $this->s3->get_object($this->bucket, $this->_make_path($user_id, $project_id) . $file, $opt);
//get filename.
$file_name = explode('?', basename($response));
//add filename to array
$local_files[] = $file_name[0];
//copy the file from aws to local server.
if(copy($response, $this->local_file_path . $this->folder . '/' . $file_name[0])) {
$zip->addFile($this->local_file_path . $this->folder . '/' . $file_name[0], $file_name[0]);
}
}
//close zip
$zip->close();
//die(var_dump(file_exists($this->filename)));
//kill each temp file
/*foreach ($local_files as $file) {
unlink($this->local_file_path . $this->folder . '/' . $file);
}*/
//load download helper.
$this->ci->load->helper('download');
//download
stream_download("APP_{$project_name}_" . time() . ".zip", $this->filename, $cookie);
}
The Download Helper
function stream_download($filename = '', $data = '', $cookie = NULL)
{
//die($cookie);
if ($filename == '' OR $data == '')
{
return FALSE;
}
// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if (FALSE === strpos($filename, '.'))
{
return FALSE;
}
// Grab the file extension
$x = explode('.', $filename);
$extension = end($x);
// Load the mime types
if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
}
elseif (is_file(APPPATH.'config/mimes.php'))
{
include(APPPATH.'config/mimes.php');
}
// Set a default mime if we can't find it
if ( ! isset($mimes[$extension]))
{
$mime = 'application/octet-stream';
}
else
{
$mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
}
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
{
header('Content-Type: "'.$mime.'"');
header('Set-Cookie: fileDownloadToken="'.$cookie.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".filesize($data));
}
else
{
header('Content-Type: "'.$mime.'"');
header('Set-Cookie: fileDownloadToken="'.$cookie.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".filesize($data));
}
flush();
}
JAVASCRIPT
downloadSelectedFiles: function(e) {
//window.XmlHttpRequest = new XmlHttpRequest();
console.log("Block UI");
var that = this;
var url = config.base + "projects/download_multi";
var projectId = $("li.selected").find('li.js-select-file').data('projectid');
var images = {};
images.hashes = [];
var token = new Date().getTime();
$("li.selected").each(function(i){
images.hashes.push($(this).find('li.js-select-file').data('filename'));
});
//window.location.href = url;
$.post(url, { files: images.hashes, projectid: projectId, downloadToken: token }, function(data){
var fileDownloadCheckTimer = window.setInterval(function() {
console.log("checking...");
var cookieValue = $.cookie('fileDownloadToken');
console.log(parseInt(cookieValue), parseInt(token));
if( parseInt(cookieValue) == parseInt(token) ) {
that.finishDownload()
} else {
console.log("Don't Match");
}
}, 1000);
/*var iframe = document.createElement("iframe");
iframe.src = config.base + data;
iframe.style.display = "none";
document.body.appendChild(iframe);
return false;*/
});
},
finishDownload: function() {
window.clearInterval(fileDownloadCheckTimer);
$.removeCookie('fileDownloadToken');
console.log("Unblock UI");
}
One thing I have noticed is that when I am checking to see of the cookie value and the token match one is a string and the other an int. Other that I also not that I only get the headers in my reposonse, I never actually get the download window.
Related
I am trying to upload a file and some text with it using ajax, but my problem is that it's not uploading to the database. I tried to use console.log to fix the problem but all it does is redirect me to the home page of my website, so it means there's an error. Am I doing something wrong? Please help me.
Javascript:
<script>
$(document).ready(function() {
$("#post-btn").click(function(e) {
var fd = new FormData();
var pst = ("#txt").value;
var files = document.getElementById("fileToUpload").files[0];
e.preventDefault();
// Check if file selected or not
if(('#fileToUpload').length != 0 ){
fd.append('fileToUpload',files[0]);
$.ajax({
url: 'posting.php',
type: 'post',
data: {pst: txt, fileToUpload: fd},
contentType: false,
processData: false,
complete: function(r){
if(r != 0){
console.log(r.responseText);
}else{
alert('file not uploaded');
}
},
});
}else{
alert("Select a file!");
}
});
});
</script>
posting.php:
<?php
$thePst = $_POST['txt'];
if (strpos($thePst, '<script>') !== false) { echo "<script>history.go(-1)</script>";
exit();
} else {
session_start();
if (isset($_POST['txt'])) {
?>
<?php
$sender = $_SESSION['username'];
$post1 = $_POST['txt'];
$post = nl2br($post1);
$submit = $_POST['submit'];
$host = "localhost";
$user = "root";
$pass = "";
$dbName = "posts";
$id = $_SESSION['id'];
$img = $_SESSION['img'];
$stringLength = strlen($post);
if (isset($post) && $stringLength <= 550 && strpos($post, '<script>') !== true) {
$target_dir = "attatch/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
if ($_FILES["fileToUpload"]["size"] > 30000) {
$uploadOk = 0;
}
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" && $imageFileType != "tiff" && $imageFileType != "mp4" && $imageFileType != "mov" && $imageFileType != "mkv") {
echo "Sorry, only JPG, JPEG, PNG, TIFF & GIF files are allowed.";
$uploadOk = 0;
}
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
} else {
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$random = substr(str_shuffle($permitted_chars), 0, 25);
$newfilename = $sender.".".$random.".".$imageFileType;
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], "attatch/" . $newfilename)) {
} else {
echo "Sorry, there was an error uploading your file.";
}
}
$today = date("F j, Y, g:i a");
try {
$attach = 'attatch/'.$newfilename;
$conn = new PDO("mysql:host=$host;dbname=$dbName", $user, $pass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$preparedStatement = $conn->prepare('INSERT INTO posts (sender, post, sender_id, image_attach, sender_img, date) VALUES (:sender, :post, :sender_id, :image_attach, :sender_img, :tod)');
$preparedStatement->bindParam(':sender', $sender);
$preparedStatement->bindParam(':post', $post);
$preparedStatement->bindParam(':sender_id', $id);
$preparedStatement->bindParam(':image_attach', $attach);
$preparedStatement->bindParam(':sender_img', $img);
$preparedStatement->bindParam(':tod', $today);
$preparedStatement->execute();
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
} finally {
$sess = $_SESSION['id'];
echo "<script>history.go(-1)</script>";
}
$conn = null;
} else {
echo "<script>history.go(-1)</script>";
}
?>
<?php
}else{
header("Location: index");
exit();
}
?>
<?php } ?>
Your help is appreciated.
You need to:
Include all the data you want in the FormData object
Pass the FormData object to data: directly without wrapping it in another object
I'm trying to set an http_response_code(); in PHP to fire an according if-statement in the fetch API response. But the response.status in JavaScript is always 200 OK. I'm really stuck with this.
What am I doing wrong?
Here is the JavaScript bit:
fetch(url, {
method: 'POST',
body: formData
})
.then(response => {
if (response.status === 422) {
console.log(
'The upload did not work. Please make sure your files are images and no bigger than 2MB.'
);
}
})
.catch(error => {
console.log('Error: ', error);
});
}
And in PHP:
if ($_SERVER['REQUEST_METHOD'] === 'POST' ) {
if (isset($_POST['folder'])) {
$folder = $_POST['folder'];
} else {
$folder = 'new-folder';
}
if (isset($_FILES['files'])) {
$errors = [];
$path = $_SERVER['DOCUMENT_ROOT'] . '/data/uploads/images/' . $folder . "/";
// if folder does not exist, create it
if (!file_exists($path)) {
mkdir($path, 0777, true);
} else {
// stuff
}
$extensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
$pattern = "#^(image/)[^\s\n<]+$#i";
$all_files = count($_FILES['files']['tmp_name']);
for ($i = 0; $i < $all_files; $i++) {
$file_name = $_FILES['files']['name'][$i];
$file_tmp = $_FILES['files']['tmp_name'][$i];
$file_type = $_FILES['files']['type'][$i];
$file_size = $_FILES['files']['size'][$i];
$tmp = explode('.', $_FILES['files']['name'][$i]);
$file_ext = strtolower(end($tmp));
$file = $path . $file_name;
$verifyimg = getimagesize($_FILES['files']['tmp_name'][$i]);
try {
if(!preg_match($pattern, $verifyimg['mime'])) {
throw new Exception("Only image files are allowed!");
}
// here goes more validation like this
if (empty($errors)) {
move_uploaded_file($file_tmp, $file);
}
} catch (Exception $exception) {
echo $exception->getMessage();
// Get the current response code and set a new one
http_response_code(422);
// Get the new response code
http_response_code();
}
}
}
}
I'm creating a mobile web app where user will be able to upload its picture and use it as an avatar. Testing it in android studio emulator everything works fine and the successful function alerts that everything is done. However my $_POST and $_FILES are empty.
JS:
var pictureSource; // picture source
var destinationType; // sets the format of returned value
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
pictureSource = navigator.camera.PictureSourceType;
destinationType = navigator.camera.DestinationType;
}
function clearCache() {
navigator.camera.cleanup();
}
var retries = 0;
function onCapturePhoto(fileURI) {
var win = function (r) {
clearCache();
retries = 0;
alert('Done!');
}
var fail = function (error) {
if (retries == 0) {
retries ++
setTimeout(function() {
onCapturePhoto(fileURI)
}, 1000)
} else {
retries = 0;
clearCache();
alert('Ups. Something wrong happens!');
}
alert(error);
}
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
options.mimeType = "image/jpeg";
var params = {};
params.username = curr_username;
alert('username: ' + params.username);
options.params = params;
var ft = new FileTransfer();
ft.upload(fileURI, encodeURI("some-server/file_upload.php"), win, fail, options, true);
}
function capturePhoto() {
navigator.camera.getPicture(onCapturePhoto, onFail, {
quality: 100,
destinationType: destinationType.FILE_URI
});
}
function onFail(message) {
alert('Failed because: ' + message);
}
PHP:
<?php
$con = mysqli_connect("localhost","db_user","db_user_pw","db_name") or die(mysqli_connect_error());
// ako u javasdcriptu nemaš pristup user_id-u, treba poslat username i ovdje fetchat iz baze odgovarajući user_id
$output = print_r($_POST, true);
file_put_contents('username.txt', $output);
$output = print_r($_FILES, true);
file_put_contents('file.txt', $output);
$username = $_POST['username'];
$tmp_file_name = $_FILES["file"]["tmp_name"];
$file_name = "images/" . $username . '.jpg';
// remove the file if exists
if(file_exists($file_name)) {
unlink($file_name);
}
// upload new file
move_uploaded_file($tmp_file_name, $file_name);
$file_name = "path_to_images_folder/".$file_name;
// update database
$q = mysqli_query($con,"UPDATE users SET avatar = '$file_name' WHERE id = (SELECT id WHERE username = '$username')");
if($q)
echo "success";
else
echo "error";
?>
Any ideas why this is happening since i'm loosing my mind
var imgAlums = window.document.getElementsByClassName("imgAlu");
var photos= [];
for (var i = 0; i < imgAlums.length; i++) {
photos.push(imgAlums[i].currentSrc);
}
//the photos array is filled //photos[0]=
data:image/;base64,/9j/4AAQSkZJRgABAQAAAQA...;
//photos[1]=data:image/;base64,/9j/4AAFWEJDKWMDCIWUEIOD...;
$.ajax({
type: 'POST',
url: '<?= URL_PROYECTO_SEGURO ?>/panel/assets/php/generateZipPhotos.php',
data: {"photos": JSON.stringify(photos)},
success: function (data) {
console.log(data);
alert("Operacion realizada con exito");
}
});
PHP code:
$nameZip = "test.zip";
$zip = new ZipArchive();
$zip->open($nameZip, ZipArchive::OVERWRITE);
$zip->addEmptyDir("Photos");
$photos= json_decode($_POST["photos"], true);
for ($i = 0; $i < count($photos); $i++) {
$data = $photos[$i];
$data = str_replace('data:image/png;base64,', '', $data);
$data = str_replace(' ', '+', $data);
$data = base64_decode($data);
$zip->addFromString("Photos/Photo" . $i . ".png", $data);
}
$zip->close();
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$nameZip");
header("Content-Transfer-Encoding: binary");
readfile($nameZip);
unlink($nameZip);
But does not generate the zip file correctly.
[edit]The zip file is generated but this has nothing inside. The problem is when you write in the zip file. The photo is misspelled
I am running into issues when uploading an image sent to PHP via JS. I can upload the image fine, but I would to resize the image before moving it to it's new destination. I can also rename the image without any issues. It's really just the resizing that is the issue here.
After a lot of searching I have seen a lot of questions regarding this on SO, which is how I got to where I am now, but not one that answers this 100%. If you know of a question/answer already on SO please link me to the correct article.
Any help is much appreciated, thanks.
Here is the JS
var test = document.querySelector('#afile');
test.addEventListener('change', function() {
var file = this.files[0];
var fd = new FormData();
fd.append('afile', file);
// These extra params aren't necessary but show that you can include other data.
fd.append('id', burgerId);
var xhr = new XMLHttpRequest();
// why wont this work in the actions directory?
xhr.open('POST', 'actions/upload.php', true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
var uploadProcess = document.getElementById('uploadProcess');
uploadProcess.setAttribute('style', 'width: ' + percentComplete + '%;');
// uploadProcess.innerHTML = parseInt(percentComplete) + '% uploaded';
}
};
xhr.onload = function() {
if (this.status == 200) {
var resp = JSON.parse(this.response);
image = 'img/' + resp.newFileName;
sessionStorage.setItem('burgerLoc', image);
var image = document.createElement('img');
image.src = resp.dataUrl;
document.body.appendChild(image);
};
};
xhr.send(fd);
// upImage(id)
}, false);
Here is the markup
<input type="file" name="afile" id="afile" accept="image/*"/>
Here is the PHP
$image = $_FILES['afile']['name'];
$image_tmp = $_FILES['afile']['tmp_name'];
$image_type = $_FILES['afile']['type'];
function getName($str) {
$parts = explode('.',$str);
$imgName = str_replace(' ', '_',$parts[0]);
return $imgName;
}
function getExtension($str) {
$parts = explode('.',$str);
$ext = $parts[1];
return $ext;
}
$image_name = stripslashes($image);
$name = getName($image_name);
$image_ext = getExtension($image_name);
$ext = strtolower($image_ext);
if($ext == 'jpg' || $ext == 'jpeg' ) {
$ext = 'jpg';
$src = imagecreatefromjpeg($image_tmp);
} else if($ext == 'png') {
$src = imagecreatefrompng($image_tmp);
} else {
$src = imagecreatefromgif($image_tmp);
}
$file_content = file_get_contents($image_tmp);
$data_url = 'data:' . $image_type . ';base64,' . base64_encode($file_content);
list($width,$height) = getimagesize($image_tmp);
// width of the main image
$new_width = 748;
$new_height = ($height / $width) * $new_width;
$img_dest = imagecreatetruecolor($new_width,$new_height);
imagecopyresampled($img_dest,$src,0,0,0,0,$new_width,$new_height,$width,$height);
// rename the file
$new_file_name = strtolower($_REQUEST['id'] . '.' . $ext);
$new_file_location = '../img/' . $new_file_name;
imagejpeg($img_dest,$new_file_name,100);
move_uploaded_file($image_tmp, $new_file_location);
imagedestroy($src);
imagedestroy($img_dest);
$json = json_encode(array(
'dataUrl' => $data_url,
'extension' => $ext,
'id' => $_REQUEST['id'],
'name' => $image,
'newFileName' => $new_file_name,
'type' => $image_type
));
echo $json;
I would maybe try installing ImageMagick in your linux distribution and try to use this function to resize the image
http://php.net/manual/en/imagick.resizeimage.php
I have reproduced your script on my webserver... I have made modifications and came up with this.
The most significant modification is that I am using exact paths in the file locations, and that I am moving the tmp file to a real file, load that real file, resize that real file instead of trying it to do with the tmp uploaded file.
PHP:
<?php
$image = $_FILES['afile']['name'];
$image_tmp = $_FILES['afile']['tmp_name'];
$image_type = $_FILES['afile']['type'];
function getName($str) {
$parts = explode('.',$str);
$imgName = str_replace(' ', '_',$parts[0]);
return $imgName;
}
function getExtension($str) {
$parts = explode('.',$str);
$ext = $parts[1];
return $ext;
}
$image_name = stripslashes($image);
$name = getName($image_name);
$image_ext = getExtension($image_name);
$ext = strtolower($image_ext);
$outputfolder = "/var/www/html/wp-content/";
$new_file_name = strtolower($_REQUEST['id'] . '.' . $ext);
$new_file_location = $outputfolder.$new_file_name;
move_uploaded_file($image_tmp, $new_file_location);
if($ext == 'jpg' || $ext == 'jpeg' ) {
$ext = 'jpg';
$src = imagecreatefromjpeg($new_file_location);
} else if($ext == 'png') {
$src = imagecreatefrompng($new_file_location);
} else {
$src = imagecreatefromgif($new_file_location);
}
list($width,$height) = getimagesize($new_file_location);
// width of the main image
$new_width = 748;
$new_height = ($height / $width) * $new_width;
$img_dest = imagecreatetruecolor($new_width,$new_height);
imagecopyresampled($img_dest,$src,0,0,0,0,$new_width,$new_height,$width,$height);
$resizedLocation = $outputfolder."resized_".$new_file_name;
imagejpeg($img_dest,$resizedLocation,100);
imagedestroy($src);
imagedestroy($img_dest);
$file_content = file_get_contents($resizedLocation);
$data_url = 'data:image/jpeg;base64,' . base64_encode($file_content);
$json = json_encode(array(
'dataUrl' => $data_url,
'extension' => $ext,
'id' => $_REQUEST['id'],
'name' => $image,
'newFileName' => $new_file_name,
'type' => $image_type
));
echo $json;
?>
Your HTML/JS stays untouched.
Now this works for me flawlessly, the only thing you have to make sure
the $outputfolder is writeable by the linux user under which the webeserver executing the php script is runnging (typically web-data...)
My web server:
CentOS Linux release 7.0.1406 (Core)
php.x86_64 5.4.16-23.el7_0.3
apache x86_64 2.4.6