How do I store the images instead of base64 in Laravel - javascript

Good Day. Please, I need your assistance. Building a laravel website in which tinymce is/was implemented in a some textareas. The challenge is that if images are uploaded in the editor, they are stored as base64 encoding. This slows down the server. I had to change my data type to longtext in my database. How do I store the images instead of base64? And how do I read the stored images.
My codes are shown below
My Controller
public function create(Request $request){
$categories = BlogCategory::all();
$tags = Tag::all();
if($request->isMethod('post')){
//dd($request);
$data = $request->except('name');
$post = new Post;
//Title
$post->title = $request->title;
//Slug
$post->publish_date = new Carbon;
$slug = $this->createSlug($request->title);
$post->slug = $slug;
//Category
if($request->category_id == "Choose Category")
{
Session::flash('failure','Please Select A Category To Proceed!');
return redirect()->back();
}else{
$post->category_id = $request->category_id;
}
//Body
$post->body = $request->body;
//Author
if(isset($request->author)){
$post->author = $request->author;
$post->author_slug = Str::slug($post->author,'-');
}else{
$post->author = "";
$post->author_slug = "";
}
//User ID
$post->user_id = Auth::user()->id;
//Keywords
if(isset($request->keywords)){
$post->keywords = $request->keywords;
}else{
$post->keywords = "";
}
//Description
if(isset($request->description)){
$post->description = $request->description;
}else{
$post->description = "";
}
//Publish
if(isset($request->publish)){
if($request->publish == 'draft'){
$post->publish = 0;
}elseif($request->publish == 'publish'){
$post->publish = 1;
$post->publish_date = new Carbon;
}
}
//Comment
if(isset($request->comments)){
if($request->comments = "on"){
$post->comment = 1;
}
}
//Image
if($request->hasFile('image')){
$img_temp = $request->file('image');
if($img_temp->isValid()){
$extension = $img_temp->getClientOriginalExtension();
$filename = 'mohvisuals'.rand(111,9999).'.'.$extension;
$large_image_path = 'images/backend_images/posts/large/'.$filename;
$medium_image_path = 'images/backend_images/posts/medium/'.$filename;
//Resize Images
Image::make($img_temp)->save($large_image_path);
Image::make($img_temp)->fit(500,400)->save($medium_image_path);
//Store Images
$post->image =$filename;
}
}
$post->save();
$post->tags()->sync($request->tags,false);
Session::flash('success',' Post Created Successfully!');
return redirect()->back();
}
return view('back_end.blog.posts.create')->with(compact('categories','tags'));
}

Your title/description says something, but your code says something else.
To store the file in database, the column type must be BINARY/BLOB.
To store the filename in database and the file on disk, colum type should be VARCHAR relative to the maximum filename length.
Do not convert files to base64 unless they're small, as their size will increase around x3 times.
To store file in database you can use this code. Inside your controller:
if ($request->hasFile('file'))
{
// If you want to resize the image, use the following method to get temporary file's path.
$request->file('file')->getPathName();
// `get()` retrieves file's content in binary mode
$post->image = request->file('file')->get();
}

Related

If image url not exist on server replace url with other (multiple time)

I made lastposter avatar for my forum system.
What i want : when user avatar img not exist change file type multiple time. Such example; if user_{userid}_avatar.png not exist change url to user_{user_id}_avatar.jpg and again it's not exist change to user_{userid}_avatar.gif and etc.({user_id} coming as php variable that's no matter).
<div class="lpavatar"><img src="/avatar/user_{user_id}.png"/></div>
<div class="lpavatar"><img src="/avatar/user_{user_id}.png"/></div>
<div class="lpavatar"><img src="/avatar/user_{user_id}.png"/></div>
You can do something like this:
Javascript:
var img_types = ['jpeg', 'gif', 'png'];
var avatar = '';
for(var i=0;i<img_types.length();i++) {
avatar = new File("/path/to/avtar." + img_types[i]);
// See if the file exists
if(avatar.exists()){
break;
}
}
PHP:
<?php
// put allowed image types in this array
$img_types = ['jpeg', 'gif', 'png'];
// avatar URL will be stored in here
$avatar = '';
// loop over the image_types array
foreach($img_types as $img_type) {
$avatar = '/path/to/user_{userid}_avatar.' . $img_type;
// check if the files exists
if(file_exists($avatar)) {
// exit the foreach loop, because we found the image
break;
}
}
?>
You can use a function like this.
function image_exists(image_url){
var http = new XMLHttpRequest();
http.open('HEAD', image_url, false);
http.send();
return http.status != 404;
}

PDF file not downloading or being saved to folder

I posted about this issue not that long ago, and I thought I had figured it out but nothing is happening.
Issue: I am trying to generate a PDF file that captures the signature of a client. Essentially they type in their name in a box and that name gets displayed in the pdf.php file along with all the other information(e.g. date, terms & conditions etc..).
I created a class that extends from FPDF and though JavaScript I am sending the name that gets filled and it gets processed through that pdf.php file and should return a "signed" pdf file.
However my pdf file is not downloading, saving or any of the options (I, D, F, S).
Below is a snippet of that section in my code.
pdf.php
$tempDir = "C:/PHP/temp/";
$thisaction = filter_input(INPUT_POST, 'action', FILTER_SANITIZE_STRING);
$answers = filter_input(INPUT_POST, 'encFormData');
$decFD = json_decode($answers);
$pdf = new WaiverFPDF();
// Pull values from array
$returnVals = array();
$returnVals['result'];
$returnVals['html'] = '';
$returnVals['errorMsg'] = '';
//the name of the person who signed the waiver
$name = $decFD->signWaiver;
$today = date('m/d/Y');
if($thisaction == 'waiverName'){
// Generate a new PDF
$pdf = new WaiverFPDF();
$pdf->AddPage()
$pdfFile = "Waiver". $name . ".pdf";
....
// Output form
$pdf->Write(8, 'I HEREBY ASSUME ALL OF THE RISKS...');
// Line Break
$pdf-> all other info...
$outFile = $tempDir . $pdfFile;
//output pdf
$pdf->Output('D', $pdfFile);
$returnVals['result'] = true;
}
else{
$returnVals['errorMsg'] = "There was an error in waiver.php";
$returnVals['result'] = false;
}
echo json_encode($returnVals);
?>
.js file (JSON)
function sendWaiver(){
var formHash = new Hash();
formHash.signWaiver = $('signWaiver').get('value');
console.log ("name being encoded");
waiverNameRequest.setOptions({
data : {
'encFormData' : JSON.encode(formHash)
}
}).send();
return true;
}
waiverNameRequest = new Request.JSON({
method : 'post',
async : false,
url : 'pdf.php',
data : {
'action' : 'waiverName',
'encFormData' : ''
},
onRequest : function() {
// $('messageDiv').set('html', 'processing...');
console.log("waiver onRequest");
},
onSuccess : function(response) {
$('messageDiv').set('html', 'PDF has been downloaded');
if (response.result == true) {
console.log('OnSuccess PDF created');
} else {
$('messageDiv').set('html', response.errorMsg);
console.log('PDF error');
}
}
});
I know my error handling is very simple, but all I am getting is success messages, but no generated pdf file... I'm not sure what i am doing wrong. I also made sure the file (when i save to a file) is writable.
class_WaiverFPDF.php
class WaiverFPDF extends FPDF
{
// Page header
function Header()
{
// Arial bold 15
$this->SetFont('Arial','B',12);
// Position XY X=20, Y=25
$this->SetXY(15,25);
// Title
$this->Cell(179,10, 'Accident Waiver ','B','C');
// Line break
$this->Ln(11);
}
// Page footer
function Footer()
{
// Position from bottom
$this->SetY(-21);
// Arial italic 8
$this->SetFont('Arial','I',8);
$this->Ln();
// Current date
$this->SetFont('Arial','I',8);
// $this->Cell(179,10,$today,0,1,'R',false);
// $today= date('m/d/Y');
$this->Cell(115,10,' Participant Name',0,0,'C');
$this->Cell(150,10,'Date',0,'C',false);
// Page number
//$this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
}
}

How can I enable user to select one image from the multiple images that he has just uploaded without refreshing the page?

I have a form where user can upload multiple images. I need a way to enable user to select one image from the images he just uploaded as his main picture before submitting the form.
I have loaded the previews using JavaScript file reader. I have tried to add a name via JavaScript to the image user has selected, so it can be accessed as a post element in the PHP script. But it is not working since it cannot be accessed as a file. I have spent 3 full days over this before posting this question. It'll be a huge help I anyone could tell me on how to approach this problem.
Following is the form :
<input type="file" name="files[]" multiple="true" id="file">
<div class="list"></div>
Javascript code for loading previews:
var imagesPreview = function(input, p) {
var id=1;
if (input.files) {
var filesAmount = input.files.length;
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function(event) {
$($.parseHTML('<img class="thumb" id="'+id+'">')).attr('src', event.target.result).appendTo(p);
id++;
}
reader.readAsDataURL(input.files[i]);
}
}
};
PHP code for uploading files:
$total = count($_FILES['files']['name']);
// Loop through each file
for($i=0; $i<$total; $i++) {
//Get the temp file path
$tmpFilePath = $_FILES['files']['tmp_name'][$i];
//Make sure we have a filepath
if ($tmpFilePath != ""){
//Setup our new file path
$newFilePath = "gig_pics/" . $_FILES['files']['name'][$i];
//Upload the file into the temp dir
move_uploaded_file($tmpFilePath, $newFilePath);
$file_sql = "INSERT INTO `gig_pics`(id,gig_id,pic) VALUES ('','$gid','$newFilePath')";
$file_res = mysqli_query($conn,$file_sql);
}
}
And after adding the name with jquery, I tried accessing the image as post
$main_img_path = $_POST['selectImage'];
$main_img_path = $_FILES['selectImage'];
But I could do anything.
I think your problem lies in the way you are selecting the specific file from the list of files:
$main_img_path = $_FILES['selectImage'];
I've not used PHP in a while, but in my opinion if you are already looping through the files on the server, why not check for the main image while looping? Something like this (assuming $_POST['selectImage'] contains the temp file name of the selected image):
$total = count($_FILES['files']['name']);
// Loop through each file
for($i=0; $i<$total; $i++) {
//Get the temp file path
$tmpFilePath = $_FILES['files']['tmp_name'][$i];
//Make sure we have a filepath
if ($tmpFilePath != ""){
if ($tmpFilePath === $_POST['selectImage']) {
// This is the selected image
}
//Setup our new file path
$newFilePath = "gig_pics/" . $_FILES['files']['name'][$i];
//Upload the file into the temp dir
move_uploaded_file($tmpFilePath, $newFilePath);
$file_sql = "INSERT INTO `gig_pics`(id,gig_id,pic) VALUES ('','$gid','$newFilePath')";
$file_res = mysqli_query($conn,$file_sql);
}
}
Like I said, this depends on what $_POST['selectImage'] contains as I'm not sure what you are storing there.

Using CKEditor custom filebrowser and upload with ASP.Net MVC

I have a MVC app that Im trying to use CKEditor with. One example I was looking at is here but there are many others. So far so good, but one section im still curious about, is the js that sends the selected file name back to the file upload dialog textbox.
<script type="text/javascript">
$(document).ready(function () {
$(".returnImage").click("click", function (e) {
var urlImage = $(this).attr("data-url");
window.opener.updateValue("cke_72_textInput", urlImage);
window.close();
});
});
</script>
In particular, the cke_72_textInput element. My example wasnt working initially, until I opened chrome dev tools and found the actual id of the textinput, which was in my case cke_76_textInput. Why the id change I wonder? Seems a little "fragile" to refer to a specific id like this? The above js code just takes the selected image file and returns it into the textbox of the fileupload dialog.
Is there something exposed that references this textbox element indirectly without specifying it by id (via the config for example)?
On view:
$(document).ready(function () {
CKEDITOR.replace('Text-area-name', {
filebrowserImageUploadUrl: '/Controller-name/UploadImage'
});
CKEDITOR.editorConfig = function (config) {
// Define changes to default configuration here. For example:
config.language = 'de';
// config.extraPlugins = 'my_own_plugin'; // if you have any plugin
// config.uiColor = '#AADC6E';
// config.image_previewText = CKEDITOR.tools.repeat(' Hier steht dann dein guter Text. ', 8 );
// config.contentsLanguage = 'de';
config.height = 350; // 350px, specify if you want a larger height of the editor
config.linkShowAdvancedTab = false;
config.linkShowTargetTab = false;
};
CKEDITOR.on('dialogDefinition', function (ev) {
var dialogName = ev.data.name;
var dialogDefinition = ev.data.definition;
ev.data.definition.resizable = CKEDITOR.DIALOG_RESIZE_NONE;
if (dialogName == 'link') {
var infoTab = dialogDefinition.getContents('info');
infoTab.remove('protocol');
dialogDefinition.removeContents('target');
dialogDefinition.removeContents('advanced');
}
if (dialogName == 'image') {
dialogDefinition.removeContents('Link');
dialogDefinition.removeContents('advanced');
var infoTab = dialogDefinition.getContents('info');
infoTab.remove('txtBorder');
infoTab.remove('txtHSpace');
infoTab.remove('txtVSpace');
infoTab.remove('cmbAlign');
}
});
}
On Contoller:
[HttpPost]
public ActionResult UploadImage(HttpPostedFileBase file, string CKEditorFuncNum, string CKEditor, string langCode)
{
if (file.ContentLength <= 0)
return null;
// here logic to upload image
// and get file path of the image
const string uploadFolder = "Assets/img/";
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath(string.Format("~/{0}", uploadFolder)), fileName);
file.SaveAs(path);
var url = string.Format("{0}{1}/{2}/{3}", Request.Url.GetLeftPart(UriPartial.Authority),
Request.ApplicationPath == "/" ? string.Empty : Request.ApplicationPath,
uploadFolder, fileName);
// passing message success/failure
const string message = "Image was saved correctly";
// since it is an ajax request it requires this string
var output = string.Format(
"<html><body><script>window.parent.CKEDITOR.tools.callFunction({0}, \"{1}\", \"{2}\");</script></body></html>",
CKEditorFuncNum, url, message);
return Content(output);
}
I had the same problem...a little frustrating that I couldn't find any official documentation, considering this seems like a common use case.
Anyways, take a look at the quick tutorial here: http://r2d2.cc/2010/11/03/file-and-image-upload-with-asp-net-mvc2-with-ckeditor-wysiwyg-rich-text-editor/. In case the link ever breaks, here's what I did.
[HttpPost]
public ActionResult UploadImage(HttpPostedFileBase upload, string ckEditorFuncNum)
{
/*
add logic to upload and save image here
*/
var path = "~/Path/To/image.jpg"; // Logical relative path to uploaded image
var url = string.Format("{0}://{1}{2}",
Request.Url.Scheme,
Request.Url.Authority,
Url.Content(path)); // URL path to uploaded image
var message = "Saved!"; // Optional
var output = string.Format("<script>window.parent.CKEDITOR.tools.callFunction({0}, '{1}', '{2}');</script>",
CKEditorFuncNum,
url,
message);
return Content(output);
}

POSTing data serverside AND execute javascript code on submitting a form

My goal is to upload some images to a server and provide them with a description.
On clicking an upload button, this is what I want to happen:
1) a javascript function dynamically adds a form to get a description
of the images.
2) on submitting the form:
a) the description entered in the form must be available $_POST['description'] at server side.
b) the images are sent to the server using an XMLHttpRequest
In the code I wrote the description is not available $_POST['description'].
When i remove the check if(!isset($_POST['description'])), the imagefiles are perfectly uploaded.
This is my code:
javascript code
upload.onclick = uploadPrompt;
// dynamically add a form
function uploadPrompt () {
// fileQueue is an array containing all images that need to be uploaded
if (fileQueue.length < 1) {
alert("There are no images available for uploading.");
} else {
var inputDescription = document.createElement("input");
inputDescription.className = "promptInput";
inputDescription.type = "text";
inputDescription.name = "description";
var inputButton = document.createElement("button");
inputButton.id = "promptInputButton";
inputButton.type = "submit";
inputButton.innerHTML = "Start uploading";
var promptForm = document.createElement("form");
promptForm.method = "post";
promptForm.action = "upload.php";
promptForm.onsubmit = uploadQueue;
promptForm.id = "promptForm";
promptForm.appendChild(inputDescription);
promptForm.appendChild(inputButton);
document.body.appendChild(promptForm);
}
}
function uploadQueue(ev) {
ev.preventDefault();
elementToBeRemoved = document.getElementById("promptForm");
elementToBeRemoved.parentElement.removeChild(elementToBeRemoved);
while (fileQueue.length > 0) {
var item = fileQueue.pop();
// item.file is the actual image data
uploadFile(item.file);
}
}
function uploadFile (file) {
if (file) {
var xhr = new XMLHttpRequest();
var fd = new FormData();
fd.append('image',file);
xhr.upload.addEventListener("error", function (ev) {
console.log(ev);
}, false);
xhr.open("POST", "upload.php");
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.send(fd);
}
}
php code upload.php
<?php
session_start();
if (!isset($_POST['description'])) {
echo "upload:fail\n";
echo "message:No scene was specified";
exit();
}
if (isset($_FILES['image'])) {
if(!move_uploaded_file($_FILES['image']['tmp_name'], "uploads/" . $_POST['description'] . "/" . $_FILES['image']['name'])) {
echo "upload:fail\n";
}
else {
echo "upload:succes\n";
}
exit();
}
exit();
?>
I'd really advise against creating your own asynchronous file upload functionality when there is a plethora of developers who have already programmed the same thing better. Check out these options:
Blueimp's jQuery file uploader
Uploadifive (Uploadify's HTML5 implementation)
I've used these two before and they work very well. For BlueImp, you can use this option to send additional form data:
$('#fileupload').fileupload({
formData: $('.some_form').serialize()
});
The above captures a form and serializes its inputs. Alternatively, you can populate an array or object using specific values (i.e. from specific elements in your DOM):
var array = new Array();
$('.description').each(function() {
array[this.id] = this.value;
});
You'd use IDs to link your files and descriptions.

Categories

Resources