I am using Froala editor for my website. This editor have built in image upload function - image upload is working fine, but I am having trouble with response.
This is from the documentation:
The server processes the HTTP request.
The server has to process the upload request, save the image and return a hashmap containing a link to the uploaded image. The returned hashmap needs to look like: { link: 'path_to_uploaded_file/file.png' }
This is my function for returning link:
public function froala_upload()
{
header('Content-type: application/json');
$folder = 'public/img/media';
$slika = $this->site->single_upload($folder, 'jpg|jpeg|png|bmp|JPG|JPEG|PNG|BMP');
$link = array("link" => $slika);
echo json_encode($link);
}
This is JS code:
$('textarea').editable({
inlineMode: false,
imageUploadParam: "userfile",
imageUploadURL: "<?php echo base_url() ?>admin/froala_upload",
// Set the image error callback.
imageErrorCallback: function (data) {
// Bad link.
if (data.errorCode == 1) {
console.log(data);
}
// No link in upload response.
else if (data.errorCode == 2) {
console.log(data);
}
// Error during file upload.
else if (data.errorCode == 3) {
console.log(data);
}
}
});
When I upload image I get following error:
Object { errorCode=1, errorStatus="Bad link."}
And this is response that I get:
{"link":"7d59d61.jpg"}
What seem to be a problem?
Froala image upload documentation
You must return the absolute image path :
$link = array("link" => '/img/media/'.$slika);
Because Froala looks for it to http://example.com/7d59d61.jpg
The problem is that the image cannot be loaded from the returned link. You'd have to make sure that the image can be accessed from it. Froala Editor uses the link you return for src attribute from img tag. I think you'd have to do something like:
$link = array("link" => $slika . 'public/img/media');
Related
I am trying to upload image to an Etsy listing via their API v2. Their documentation have code example of image upload in PHP, in which the POST request body parameter is given like this
$params = array('#image' => '#'.$source_file.';type='.$mimetype);
How would I go about replicating this in JavaScript? I have tried sending the image blob as the image parameter but it does not seem to be working.
Edit: I am using npm oauth package. Here is my complete code that I am using to call the API.
var oauth1 = new OAuth1.OAuth(
'https://openapi.etsy.com/v2/oauth/request_token?scope=email_r%20listings_r%20listings_w%20listings_d',
'https://openapi.etsy.com/v2/oauth/access_token',
'api_key',
'api_secret',
'1.0A',
null,
'HMAC-SHA1'
);
oauth1.post(
'https://openapi.etsy.com/v2/listings/915677000/images',
req.user.etsy.oauth_token,
req.user.etsy.oauth_token_secret,
{
'listing_id': 915677000,
'image': <image has to go here>
},
'multipart/form-data',
function (e, data, response){
if (e) console.error(e);
// let body = JSON.parse(data);
console.log(data);
res.redirect('/create-listings')
});
I am using vue-wysiwyg editor in my laravel-vue application. In this editor there is an option to upload images and through incomplete documentation of this package I am able to upload the image and get public url of the uploaded file. But this package works sometimes and does not work at all sometimes.
Here is how I am using this package
main.js
import wysiwyg from "vue-wysiwyg";
Vue.use(wysiwyg, {
forcePlainTextOnPaste: true,
image: {
uploadURL: "/api/save-support-files",
dropzoneOptions: {}
},
});
/api/save-support-files
public function uploadUserFile(Request $request)
{
$uploadedFile = $request->file('file');
if (false == $uploadedFile) {
return response()->api(false, 'Kindly upload a file');
}
$allowed_file_extentions = [
'jpeg',
'png',
'jpg',
'gif',
'svg'
];
if (false == in_array($uploadedFile->getClientOriginalExtension(), $allowed_file_extentions)) {
return response()->api(false,'Allowed file types are jpeg, png, jpg, gif, svg',null);
}
$file_url = Storage::disk('public')->putFileAs('/support-files',$uploadedFile,generateRandomString('5').'.'.$uploadedFile->getClientOriginalExtension());
// return response()->api(true,'File uploaded successfully',config('app.url').'/storage/'.$file_url);
return config('app.url').'/storage/'.$file_url;
}
Issues I am facing right now:
As soon as I select image from file browser, image is uploaded through api successfully but it is not showing in editor.
Unable to select already uploaded image, I have to refresh the page and then again select file to upload it again.
Is anyone having solution to this problem ? Kindly help me out.
my upload store function look like this:
public function store(Request $request)
{
$request->validate(['file' => 'required']);
$file = $request->file('file');
if ($file->isValid()) {
$path = $file->storePublicly(now()->format('Y' . DIRECTORY_SEPARATOR . 'm' . DIRECTORY_SEPARATOR . 'd'));
return response(Storage::disk('public')->url($path), Response::HTTP_CREATED)->withHeaders(
[
'content-type' => 'text/html'
]
);
}
abort(Response::HTTP_BAD_REQUEST);
}
make sure you have set APP_URL in .env to full url (http://my-site.com)
make sure you run php artisan storage:link
I am attempting to add an "Upload Image" feature to my AjaxChat window. The upload to the server works great, but now I need to be able to return the tmp_name/location of the file that was uploaded. In my Javascript I have the following (main) code (some setup code has been omitted because it is unnecessary -- The upload works as expected):
// Set up request
var xhr = new XMLHttpRequest();
// Open connection
xhr.open('POST', 'sites/all/modules/ajaxchat/upload.php', true);
// Set up handler for when request finishes
xhr.onload = function () {
if (xhr.status === 200) {
//File(s) uploaded
uploadButton.innerHTML = 'Upload';
} else {
alert('An error occurred!');
}
};
// Send data
xhr.send(formData);
My PHP code ("upload.php") is as follows:
<?php
$valid_file = true;
echo '<script type="text/javascript">alert("PHP Code Reached");</script>';
if($_FILES['photo']['name']) {
//if no errors...
if(!$_FILES['photo']['error']) {
//now is the time to modify the future file name and validate the file
$new_file_name = strtolower($_FILES['photo']['tmp_name']); //rename file
if($_FILES['photo']['size'] > (1024000)) { //can't be larger than 1 MB
$valid_file = false;
$message = 'Oops! Your file\'s size is to large.';
exit("$message");
}
//if the file has passed the test
if($valid_file) {
//move it to where we want it to be
move_uploaded_file($_FILES['photo']['tmp_name'], '/var/www/html/images'.$new_file_name);
$message = 'Congratulations! Your file was accepted.';
exit("$message");
}
}
//if there is an error...
else {
//set that to be the returned message
$message = 'Ooops! Your upload triggered the following error: '.$_FILES['photo']['error'];
exit("$message");
}
}
?>
I can tell my PHP code is being run because the image uploads to the server. However, I read that I could generate a Javascript "alert" popup from within the PHP using the following code:
echo '<script type="text/javascript">alert("PHP Code Reached");</script>';
But the above line does not seem to be doing anything. Is this expected since I'm using an XMLHttpRequest, rather than running the PHP directly?
Ultimately my goal is to pass the name of the uploaded file back to the Javascript that called the PHP so that I can create the image url, put it in img tags, and send it to the chat window using ajaxChat.insertText() and ajaxChat.sendMessage(). I'm not sure if this is possible the way I'm running my PHP, though. How would one go about doing this?
When you use XMLHttpRequest, the output of the server script is in the responseText of the object. So you can do:
xhr.onload = function () {
if (xhr.status === 200) {
//File(s) uploaded
uploadButton.innerHTML = xhr.responseText;
} else {
alert('An error occurred!');
}
};
If you want to send back multiple pieces of information, such as an informative message and the name of the file, you can use JSON to encode an associative array, which will become a Javascript object when you parse it.
I have a button and onclick it will call an ajax function.
Here is my ajax function
function csv(){
ajaxRequest = ajax();//ajax() is function that has all the XML HTTP Requests
postdata = "data=" + document.getElementById("id").value;
ajaxRequest.onreadystatechange = function(){
var ajaxDisplay = document.getElementById('ajaxDiv');
if(ajaxRequest.readyState == 4 && ajaxRequest.status==200){
ajaxDisplay.innerHTML = ajaxRequest.responseText;
}
}
ajaxRequest.open("POST","csv.php",false);
ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
ajaxRequest.send(postdata);
}
I create the csv file based on the user input. After it's created I want it to prompt download or force download(preferably force). I am using the following script at the end of the php file to download the file. If I run this script in a separate file it works fine.
$fileName = 'file.csv';
$downloadFileName = 'newfile.csv';
if (file_exists($fileName)) {
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='.$downloadFileName);
ob_clean();
flush();
readfile($fileName);
exit;
}
echo "done";
But If I run it at the end of csv.php it outputs the contents of the file.csv into the page(into the ajaxDiv) instead of downloading.
Is there a way to force download the file at the end of csv.php?
AJAX isn't for downloading files. Pop up a new window with the download link as its address, or do document.location = ....
A very simple solution using jQuery:
on the client side:
$('.act_download_statement').click(function(e){
e.preventDefault();
form = $('#my_form');
form.submit();
});
and on the server side, make sure you send back the correct Content-Type header, so the browser will know its an attachment and the download will begin.
#joe : Many thanks, this was a good heads up!
I had a slightly harder problem:
1. sending an AJAX request with POST data, for the server to produce a ZIP file
2. getting a response back
3. download the ZIP file
So that's how I did it (using JQuery to handle the AJAX request):
Initial post request:
var parameters = {
pid : "mypid",
"files[]": ["file1.jpg","file2.jpg","file3.jpg"]
}
var options = {
url: "request/url",//replace with your request url
type: "POST",//replace with your request type
data: parameters,//see above
context: document.body,//replace with your contex
success: function(data){
if (data) {
if (data.path) {
//Create an hidden iframe, with the 'src' attribute set to the created ZIP file.
var dlif = $('<iframe/>',{'src':data.path}).hide();
//Append the iFrame to the context
this.append(dlif);
} else if (data.error) {
alert(data.error);
} else {
alert('Something went wrong');
}
}
}
};
$.ajax(options);
The "request/url" handles the zip creation (off topic, so I wont post the full code) and returns the following JSON object. Something like:
//Code to create the zip file
//......
//Id of the file
$zipid = "myzipfile.zip"
//Download Link - it can be prettier
$dlink = 'http://'.$_SERVER["SERVER_NAME"].'/request/download&file='.$zipid;
//JSON response to be handled on the client side
$result = '{"success":1,"path":"'.$dlink.'","error":null}';
header('Content-type: application/json;');
echo $result;
The "request/download" can perform some security checks, if needed, and generate the file transfer:
$fn = $_GET['file'];
if ($fn) {
//Perform security checks
//.....check user session/role/whatever
$result = $_SERVER['DOCUMENT_ROOT'].'/path/to/file/'.$fn;
if (file_exists($result)) {
header('Content-Description: File Transfer');
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename='.basename($result));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($result));
ob_clean();
flush();
readfile($result);
#unlink($result);
}
}
I have accomplished this with a hidden iframe. I use perl, not php, so will just give concept, not code solution.
Client sends Ajax request to server, causing the file content to be generated. This is saved as a temp file on the server, and the filename is returned to the client.
Client (javascript) receives filename, and sets the iframe src to some url that will deliver the file, like:
$('iframe_dl').src="/app?download=1&filename=" + the_filename
Server slurps the file, unlinks it, and sends the stream to the client, with these headers:
Content-Type:'application/force-download'
Content-Disposition:'attachment; filename=the_filename'
Works like a charm.
You can't download the file directly via ajax.
You can put a link on the page with the URL to your file (returned from the ajax call) or another way is to use a hidden iframe and set the URL of the source of that iframe dynamically. This way you can download the file without refreshing the page.
Here is the code
$.ajax({
url : "yourURL.php",
type : "GET",
success : function(data) {
$("#iframeID").attr('src', 'downloadFileURL');
}
});
You can do it this way:
On your PHP REST api: (Backend)
header('Content-Description:File Transfer');
header('Content-Type:application/octet-stream');
header('Content-Disposition:attachment; filename=' . $toBeDownloaded);
header('Content-Transfer-Encoding:binary');
header('Expires:0');
header('Cache-Control:must-revalidate');
header('Pragma:public');
header('Content-Length:'.filesize($toBeDownloaded));
readfile($toBeDownloaded);
exit;
On your javascript code: (FRONTEND)
const REQUEST = `API_PATH`;
try {
const response = await fetch(REQUEST, {
method: 'GET',
})
const fileUploaded = await response.blob();
const url = window.URL.createObjectURL(fileUploaded);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'YOUR_FILE_NAME_WITH_EXTENSION');
document.body.appendChild(link);
link.click();
} catch (error) {
console.log(error)
}
I'm calling a PHP Script to genereta an excel file and then download it on the fly
header('Content-Type: application/vnd.ms-excel');
header("Content-Disposition: attachment;filename=iva.xls");
$objWriter = new PHPExcel_Writer_Excel5($objPHPExcel);
$objWriter->save('php://output');
After this code I finish with:
$aReturn[]= array('result'=>true);
exit(json_encode($aReturn));
At the first moment I start calling this PHP using a submit button... then (trying to get a progress bar) I decided to call this php using javascript with following code:
$.messager.progress();
var urlProtax="taxes/processtax.php?start=" + cStartDate + '&end='+ cEndDate ;
$('#taxesForm').form('submit',{
url: urlProtax,
onSubmit: function(datt){
var isValid = $(this).form('validate');
if (!isValid){
$.messager.progress('close');
}
return isValid;
},
success: function(jdatos){
alert('alert data '+ jdatos);
data = eval('('+jdatos+')');
if(data[0]['result']===true){
$.messager.progress('close');
$('#taxesWin').window('close');
return true;
}else{
$.messager.progress('close');
var iderror = data[0]['error'];
$.messager.alert("ERROR (" + iderror +")" , gt.gettext('Unknown Error'), 'error');
$('#taxesWin').window('close');
}
},
error: function(xhr) {
alert('Error! Status = ' + xhr.status);}
});
Excel file is being created fine!!! but I never get the json response to close progress bar.
Kind Regards,
Excel files are binary, JSON doesn't support binary formats directly.
You might have better luck if you use an ascii format like CSV