Absolute path in Magento2 - path

How can I get the absolute path of a media file in Magento2?
I write a function to get the absolute path, but it is not working.
public function getAbsolutePath()
{
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
/** #var \Magento\Framework\Filesystem $filesystem */
$filesystem = $objectManager->get('Magento\Framework\Filesystem');
/** #var \Magento\Framework\Filesystem\Directory\WriteInterface $mediaDirectory */
$mediaDirectory = $filesystem->getDirectoryWrite(Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
$mediaPath = $mediaDirectory->getAbsolutePath();
return $mediaPath;
}

app/autoloader.php
contains:
/**
* Shortcut constant for the root directory
*/
define('BP', dirname(__DIR__));
One could do something like:
$mediaPath = BP.'/pub/media/';
That said, Magento\Framework\Filesystem via dependency injection is my preferred method

You can use to get media and base Absolute path in magento 2 like:
$storeManager = $_objectMedia->get('Magento\Store\Model\StoreManagerInterface');
$currentStore = $storeManager->getStore();
$mediaUrl = $currentStore->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$_baseurl = $storeManager->getStore()->getBaseUrl();
Try it's working fine for me....

/* #var \Magento\Framework\ObjectManagerInterface $om /
$om = \Magento\Framework\App\ObjectManager::getInstance();
$dir = $om->get('Magento\Framework\Filesystem');
$mediadir = $dir->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);
$path = $mediadir->create('foldername');
try it its working for me..

Relying on the BP isn't a good way to go this, BP should only be used in the low layers in Magento.
Magneto has init config values where the media directory could possibly be outside of the base path. You should rely on the \Magento\Framework\App\Filesystem\DirectoryList object instead.
In the bootstrap you can see:
\Magento\Framework\App\Bootstrap::createFilesystemDirectoryList
class Bootstrap
{
/**
* Creates instance of filesystem directory list
*
* #param string $rootDir
* #param array $initParams
* #return DirectoryList
*/
public static function createFilesystemDirectoryList($rootDir, array $initParams)
{
$customDirs = [];
if (isset($initParams[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS])) {
$customDirs = $initParams[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS];
}
return new DirectoryList($rootDir, $customDirs);
}
}
This means if you set $_SERVER variables during bootstrap:
$tmpDir = '/var/tmpfs_mount';
$applicationDir = '/var/www/html/magento';
$loggingDir = '/var/log/restricted';
$params = $_SERVER;
$filesystemsDirs = $params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS];
$filesystemsDirs[DirectoryList::CONFIG] = [DirectoryList::PATH => $applicationDir . "/var/cache"];
$filesystemsDirs[DirectoryList::MEDIA] = [DirectoryList::PATH => $tmpDir . "/var/cache"];
$filesystemsDirs[DirectoryList::GENERATED] = [DirectoryList::PATH => $tmpDir . "/generated"];
$filesystemsDirs[DirectoryList::CACHE] = [DirectoryList::PATH => $tmpDir . "/var/cache"];
$filesystemsDirs[DirectoryList::LOG] = [DirectoryList::PATH => $loggingDir . "/var/log"];
$params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS] = $filesystemsDirs;
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $params);
To do via the object manager, add the DirectoryList object to the constructor:
use \Magento\Framework\App\Filesystem\DirectoryList;
class MyModuleClass
{
/**
* #var DirectoryList
*/
private $directoryList;
/**
* #param DirectoryList $directoryList
*/
public function __construct(DirectoryList $directoryList)
{
$this->directoryList = $directoryList;
}
/**
* #var DirectoryList
*/
private $mediaPath;
public function getMediaAbsolutePath(){
if (!$this->mediaPath){
$this->mediaPath = $this->directoryList->getPath(DirectoryList::MEDIA);
}
return $this->mediaPath;
}
}
Please note this will only get you the path, but it won't validate if via the PathValidator introduced in Magento 2.3. This PathValidator ensures that the path is allowed within the installation, you'll need to validate it yourself
vendor/magento/framework/Filesystem/Directory/PathValidator.php
P.S I haven't tested the code, I've just eye'd it from memory, so if it breaks let me know.

With Object manager:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$directoryList = $objectManager->get('Magento\Framework\App\Filesystem\DirectoryList');
$media = $directoryList->getPath('media');
With dependency injection:
Use class `\Magento\Framework\App\Filesystem\DirectoryList
protected $_directoryList;
public function __construct(
...
\Magento\Framework\App\Filesystem\DirectoryList $directoryList
...
) {
$this->_directoryList = $directoryList;
}
For Root Folder
$this->_directoryList->getRoot();
For media Folder
$this->_directoryList->getPath('media');
Other Folders
// Get app folder
$this->_directoryList->getPath('app');
// Get etc Folder
$this->_directoryList->getPath('etc');
// Get public folder
$this->_directoryList->getPath('pub');
// Get var folder
$this->_directoryList->getPath('var');

you can use this:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$fileSystem = $om->get('Magento\Framework\Filesystem');
$mediaDirectory = $fileSystem->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA);

Use blow code for geting absolute url of an image you have uploaded in product page.
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$b_url = $objectManager->get('Magento\Store\Model\StoreManagerInterface')
->getStore()
->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
// here product_badge is custom image attribute code, replace it with yours attribute.
$_product = $block->getProduct();
$product_badge = $_product->getResource()->getAttribute('product_badge')->getFrontend()->getValue($_product);
?>
<img src="<?php echo $b_url.'/catalog/product'.$product_badge; ?>" />

$rootDirectory = Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Framework\Filesystem')
->getDirectoryRead(DirectoryList::MEDIA);

Related

TYPO3 8 LTS how to generate frontend page URL in CLI/Scheduler context

I'm trying to figure out how to generate absolute frontend page URLs from CLI/Scheduler context. I've created the following helper class:
class FrontendUrlProvider
{
/**
* #var ObjectManagerInterface
*/
private $objectManager;
/**
* #var LoggerInterface
*/
private $logger;
/**
* #param ObjectManagerInterface $objectManager
* #param LoggerInterface $logger
*/
public function __construct(ObjectManagerInterface $objectManager, LoggerInterface $logger)
{
$this->objectManager = $objectManager;
$this->initializeTimeTracker();
$this->logger = $logger;
}
/**
* #param int $pageId
* #param int $languageId
* #return Uri
*/
public function pageUrl($pageId, $languageId)
{
$url = '';
$this->logger->error('generating preview link');
try {
$this->initializeTypoScriptFrontend($pageId);
$this->setUpPageDomainIfCliContext($pageId);
$contentRenderer = $this->objectManager->get(ContentObjectRenderer::class);
$command = $this->linkCommand($pageId, $languageId);
$url = $contentRenderer->typoLink_URL($command);
$this->logger->error("preview link is: $url");
} catch (\Exception $exception) {
$this->logger->error($exception->getMessage());
$this->logger->error($exception->getTraceAsString());
}
return new Uri($url);
}
private function initializeTimeTracker()
{
if (!is_object($GLOBALS['TT'])) {
$GLOBALS['TT'] = new \TYPO3\CMS\Core\TimeTracker\NullTimeTracker();
}
}
/**
* #param int $pageId
*/
private function initializeTypoScriptFrontend($pageId)
{
if (isset($GLOBALS['TSFE']) && is_object($GLOBALS['TFSE'])) {
return;
}
$GLOBALS['TSFE'] = $this->objectManager->get(TypoScriptFrontendController::class, $GLOBALS['TYPO3_CONF_VARS'], $pageId, '');
$GLOBALS['TSFE']->sys_page = $this->objectManager->get(PageRepository::class);
$GLOBALS['TSFE']->sys_page->init(false);
$GLOBALS['TSFE']->tmpl = $this->objectManager->get(TemplateService::class);
$GLOBALS['TSFE']->tmpl->init();
$GLOBALS['TSFE']->connectToDB();
$GLOBALS['TSFE']->initFEuser();
$GLOBALS['TSFE']->determineId();
$GLOBALS['TSFE']->initTemplate();
$GLOBALS['TSFE']->getConfigArray();
}
/**
* #param int $pageId
*/
private function setUpPageDomainIfCliContext($pageId)
{
if (!isset($_SERVER['HTTP_HOST']) || !$_SERVER['HTTP_HOST']) {
$domainData = $GLOBALS['TSFE']->getDomainDataForPid($pageId);
if (is_array($domainData) && isset($domainData['domainName']) && !empty($domainData['domainName'])) {
$_SERVER['HTTP_HOST'] = $domainData['domainName'] ?: '';
}
}
}
/**
* #param int $pageId
* #param int $languageId
* #return array
*/
private function linkCommand($pageId, $languageId)
{
$languageQuery = http_build_query(['L' => $languageId], null, '&', PHP_QUERY_RFC3986);
return array(
'parameter' => $pageId,
'useCacheHash' => false,
'forceAbsoluteUrl' => true,
'linkAccessRestrictedPages' => true,
'additionalParams' => '&' . $languageQuery,
);
}
}
I'm at the point that it works fine in TYPO3 7 LTS, as long as there's a domain record for the root line.
However this same snippet doesn't work in TYPO3 8 LTS and I need it working for both 7 and 8 at the same time. Obviously, I have set the domain record on the root line in v8, I cleared all the caches, etc. but I can't get an absolute URL in place. I only get the relative URL. At this point I'm not that interested in realUrl or anything like that.
For TYPO3 7 I basically reverse engineered it but with TYPO3 8 it seems a bit more complicated. Do you know what can I do more to get the page frontend URL?
It seems that the issue was an internal cache of the GeneralUtility, which cached a null value for the HTTP_HOST of $_SERVER superglobal.
Therefore the following line from my example above had no effect
$_SERVER['HTTP_HOST'] = $domainData['domainName'] ?: '';
In order to make it work under the CLI/Scheduler scope I had to clear the internal cache of the GeneralUtility by calling
TYPO3\CMS\Core\Utility\GeneralUtility::flushInternalRuntimeCaches();
before making a call to $contentRenderer->typoLink_URL($command);
Now frontend URL generation works fine on both TYPO3 7 and 8 LTS.
https://wissen.netzhaut.de/typo3/extensionentwicklung/typolink-realurl-in-scheduler-tasks/
But really: I'd recommend using a curl call against a custom page which will deliver the link (sort of as a rest API) - because thereby you go around almost all issues - and there are more beyond not having tsfe (e.g. safePath \ images).

TYPO3 FAL upload frontend add title, alternative and description

I have an extension where user can upload in frontend some images to their frontend-profile. Image upload and saving to user-profile works fine, I user following code - but is there a simple way to add title, alternative and description too?
Thanks for help!
Martin
/** #var \TYPO3\CMS\Core\Resource\StorageRepository $storageRepository */
$storageRepository = $this->objectManager->get('TYPO3\CMS\Core\Resource\StorageRepository');
/** #var \TYPO3\CMS\Core\Resource\ResourceStorage $storage */
$storage = $storageRepository->findByUid('1');
#$storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
#$storage = $storageRepository->findByUid(1); # Fileadmin = 1
#$saveFolder = $storage->getFolder($this->settings['uploadFolder']);
$fileData = array();
$fileData['name'] = $_FILES['tx_key_datenwartung']['name']['logo'][0];
$fileData['type'] = $_FILES['tx_key_datenwartung']['type']['logo'][0];
$fileData['tmp_name'] = $_FILES['tx_key_datenwartung']['tmp_name']['logo'][0];
$fileData['size'] = $_FILES['tx_key_datenwartung']['size']['logo'][0];
// this will already handle the moving of the file to the storage:
$newFileObject = $storage->addFile(
$fileData['tmp_name'], $saveFolder, $userUid.'_'.$fileData['name']
);
$newFileObject = $storage->getFile($newFileObject->getIdentifier());
#$newFile = $this->fileRepository->findByUid($newFileObject->getProperty('uid'));
$newFile = $newFileObject->getUid();
$persistenceManager = $this->objectManager->get('TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager');
$persistenceManager->persistAll();
/** #var \Vendor\Myextension\Domain\Model\FileReference $newFileReference */
$newFileReference = $this->objectManager->get('Ven\Key\Domain\Model\FileReference');
$newFileReference->setFile($newFile);
$user->addLogo($newFileReference);
.... could solve it myself. just add setter to model and add texts:
/**
* Set alternative
*
* #param \xx\yy\Domain\Model\File $file
*/
public function setAlternative($alternative) {
$this->alternative = $alternative;
}
and to controller:
$newFileReference->setAlternative('your alternative text for image');

Integrating OpenLayers 3 with Cesium Viewer

I'm developing using Cesium built on top of Cesium.Viewer. Cesium lacks some features so I wish to integrate with OpenLayers. I'd like to add existing OpenLayers layers to the Cesium.Viewer as if they were "imagery layers".
I've found ol3-cesium, however this only allows an entire OpenLayers map instance to be visualized on a Cesium.Scene which it creates for you. Cesium.Viewer also creates an instance of Cesium.Scene targeted at a given DOM element.
How can I add OpenLayers layers to a Cesium.Viewer?
Some code snippets for illustration
var olLayer1= new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'sat'})
});
var olLayer2= new ol.layer.Vector({
source : ol.source.Vector();
});
var map = new ol.Map({
layers: [olLayer1, olLayer2],
target: 'map',
view: new ol.View({
})
});
Existing Cesium viewer
var viewer = new Cesium.Viewer('cesium-map', {});
// viewer setup code
ol3-cesium initialization - but this doesn't allow usage with existing viewer??
var ol3d = new olcs.OLCesium({map: map}); // map is the ol.Map instance
I just looked through the initialization code for OL3-Cesium and while it is essentially a wrapper on top of Cesium, the means that they decided to implement a Cesium environment is not going to play nicely if you want a hybrid Cesium.Viewer and an OL3 object.
I'm not sure of your comfort level with modifying JS libraries, but
what I personally would do is make my own ol3 cesium viewer class. Something like this gist I just threw together.
Just a warning, I have not tested this code yet. You may have to make some additional modifications if you receive errors. There may be a reason that the OL3-Cesium developers choose not to use the Cesium widget or viewer to initialize Cesium in their library, but I see no reason this wouldn't work.
Here is the constructor, but you would want the whole Gist as a separate file in your ol3-cesium library. Put it in the same directory as the ol3Cesium.js file.
excerpt from https://gist.github.com/maikuru/9e650bf88aed84982667
olcs.OLCesiumViewer = function(options) {
/**
* #type {!ol.Map}
* #private
*/
this.map_ = options.map;
var fillArea = 'position:absolute;top:0;left:0;width:100%;height:100%;';
/**
* #type {!Element}
* #private
*/
this.container_ = goog.dom.createDom(goog.dom.TagName.DIV,
{style: fillArea + 'visibility:hidden;'});
var targetElement = goog.dom.getElement(options.target || null);
if (targetElement) {
goog.dom.appendChild(targetElement, this.container_);
} else {
var vp = this.map_.getViewport();
var oc = goog.dom.getElementByClass('ol-overlaycontainer', vp);
if (oc) {
goog.dom.insertSiblingBefore(this.container_, oc);
}
}
/**
* Whether the Cesium container is placed over the ol map.
* #type {boolean}
* #private
*/
this.isOverMap_ = !goog.isDefAndNotNull(targetElement);
/**
* #type {!HTMLCanvasElement}
* #private
*/
this.canvas_ = /** #type {!HTMLCanvasElement} */
(goog.dom.createDom(goog.dom.TagName.CANVAS, {style: fillArea}));
this.canvas_.oncontextmenu = function() { return false; };
this.canvas_.onselectstart = function() { return false; };
goog.dom.appendChild(this.container_, this.canvas_);
/**
* #type {boolean}
* #private
*/
this.enabled_ = false;
/**
* #type {!Array.<ol.interaction.Interaction>}
* #private
*/
this.pausedInteractions_ = [];
/**
* #type {?ol.layer.Group}
* #private
*/
this.hiddenRootGroup_ = null;
/**
* #type {!Object.<Cesium.Viewer.Options>}
* #private
*/
var cesiumViewerConfig_ = (options.viewer || {}).scene3DOnly = true;
/**
* #type {!Cesium.Viewer}
* #private
*/
this.viewer_ = new Cesium.Viewer(this.container_, cesiumViewerConfig_);
/**
* #type {!Cesium.Scene}
* #private
*/
this.scene_ = this.viewer_.scene;
var sscc = this.scene_.screenSpaceCameraController;
sscc.inertiaSpin = 0;
sscc.ineartiaTranslate = 0;
sscc.inertiaZoom = 0;
sscc.tiltEventTypes.push({
'eventType': Cesium.CameraEventType.LEFT_DRAG,
'modifier': Cesium.KeyboardEventModifier.SHIFT
});
sscc.tiltEventTypes.push({
'eventType': Cesium.CameraEventType.LEFT_DRAG,
'modifier': Cesium.KeyboardEventModifier.ALT
});
sscc.enableLook = false;
this.scene_.camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;
/**
* #type {!olcs.Camera}
* #private
*/
this.camera_ = new olcs.Camera(this.scene_, this.map_);
/**
* #type {!Cesium.Globe}
* #private
*/
this.globe_ = this.scene_.globe;
this.scene_.skyAtmosphere = new Cesium.SkyAtmosphere();
var synchronizers = goog.isDef(options.createSynchronizers) ?
options.createSynchronizers(this.map_, this.scene_) :
[
new olcs.RasterSynchronizer(this.map_, this.scene_),
new olcs.VectorSynchronizer(this.map_, this.scene_)
];
for (var i = synchronizers.length - 1; i >= 0; --i) {
synchronizers[i].synchronize();
}
if (this.isOverMap_) {
// if in "stacked mode", hide everything except canvas (including credits)
var credits = goog.dom.getNextElementSibling(this.canvas_);
if (goog.isDefAndNotNull(credits)) {
credits.style.display = 'none';
}
}
this.camera_.readFromView();
this.cesiumRenderingDelay_ = new goog.async.AnimationDelay(function(time) {
this.scene_.initializeFrame();
this.handleResize_();
this.scene_.render();
this.enabled_ && this.camera_.checkCameraChange();
this.cesiumRenderingDelay_.start();
}, undefined, this);
};
There are some internal classes which emulate layers using the Cesium API calls. These are in the documentation so I'm assuming "public" API.
The layers must be added to a map and cannot be used in isolation. This is required as the map defines the projection etc.
For example VectorSynchronizer creates listeners on the underlying layers and keeps the Cesium scene in sync...
new olcs.VectorSynchronizer(map, viewer.scene);

how to set the correct path for file download in zendframework2

my controller:
public function downloadAction()
{
$param['filename'] = $this->params()->fromRoute('filename');
$param['foldername'] = $this->params()->fromRoute('foldername');
$fileName = $param['filename']; //bala.pdf
$folderName = $param['foldername']; //j1005
$fileContents = file_get_contents($fileName);
$response = $this->getResponse();
$response->setContent($fileContents);
$headers = $response->getHeaders();
$headers->clearHeaders()
->addHeaderLine('Content-Type', 'application/pdf')
->addHeaderLine('Content-Disposition', 'attachment; filename="' .$fileName . '"')
->addHeaderLine('Content-Length', strlen($fileContents));
return $this->response;
}
my file location is ./data/basepaper/j1005/bala.pdf , but i dont know how to set the path for download the file
It could be good for you to assign your variable properly (initialise empty array for instance before use) and to use your variables (the array is only used to assign the variables again...).
Concerning the current problem, you need to understand the basic of the file management on ZF2, and therefore read the index.php:
<?php
/**
* This makes our life easier when dealing with paths. Everything is relative
* to the application root now.
*/
chdir(dirname(__DIR__));
Which means you can refer to any file from the root directory of your project.
So your code become:
public function downloadAction()
{
// Combine assignation (unused array, and non initialised...)
$fileName = $this->params()->fromRoute('filename');
$folderName = $this->params()->fromRoute('foldername');
$fileContents = file_get_contents("data/basepaper/{$folderName}/{$fileName}");
$response = $this->getResponse();
$response->setContent($fileContents);
$headers = $response->getHeaders();
$headers->clearHeaders()
->addHeaderLine('Content-Type', 'application/pdf')
->addHeaderLine('Content-Disposition', 'attachment; filename="' .$fileName . '"')
->addHeaderLine('Content-Length', strlen($fileContents));
return $this->response;
}

nicUpload says "Invalid Upload ID", cant make it works

Im trying to implement nicEdit with the nicupload plugin, but when I select a file to upload it says "Failed to upload image", and the server response says "Invalid Upload ID".
This is the code that calls the script and initializes:
<script src="http://js.nicedit.com/nicEdit-latest.js" type="text/javascript"></script>
<script type="text/javascript">//<![CDATA[
bkLib.onDomLoaded(function() {
new nicEditor({uploadURI : '../../nicedit/nicUpload.php'}).panelInstance('area1');
});
//]]>
</script>
The path to nicUpload.php is correct, and the code is the one that can be found in the documentation: http://nicedit.com/src/nicUpload/nicUpload.js
I made the upload folder changes, and set write permissions. According to the documentation (http://wiki.nicedit.com/w/page/515/Configuration%20Options), thats all, but i keep getting errors. Any ideas?
After looking for an solution a long time (lot of posts without real solution), i now fixed the code myself. I'm now able to upload an image to my own server. Thx to firebug and eclipse ;-)
The main problem is that the nicUpload.php is old and not working with the current nicEdit-Upload function.
Missing is the error handling, feel free to add this...
Add the nicEditor to your php file and configure it to use the nicEdit.php:
new nicEditor({iconsPath : 'pics/nicEditorIcons.gif', uploadURI : 'script/nicUpload.php'}
Download the nicEdit.js uncompressed and change the following lines in nicEdit.js:
uploadFile : function() {
var file = this.fileInput.files[0];
if (!file || !file.type.match(/image.*/)) {
this.onError("Only image files can be uploaded");
return;
}
this.fileInput.setStyle({ display: 'none' });
this.setProgress(0);
var fd = new FormData();
fd.append("image", file);
fd.append("key", "b7ea18a4ecbda8e92203fa4968d10660");
var xhr = new XMLHttpRequest();
xhr.open("POST", this.ne.options.uploadURI || this.nicURI);
xhr.onload = function() {
try {
var res = JSON.parse(xhr.responseText);
} catch(e) {
return this.onError();
}
//this.onUploaded(res.upload); // CHANGE HERE
this.onUploaded(res);
}.closure(this);
xhr.onerror = this.onError.closure(this);
xhr.upload.onprogress = function(e) {
this.setProgress(e.loaded / e.total);
}.closure(this);
xhr.send(fd);
},
onUploaded : function(options) {
this.removePane();
//var src = options.links.original; // CHANGE HERE
var src = options['url'];
if(!this.im) {
this.ne.selectedInstance.restoreRng();
//var tmp = 'javascript:nicImTemp();';
this.ne.nicCommand("insertImage", src);
this.im = this.findElm('IMG','src', src);
}
var w = parseInt(this.ne.selectedInstance.elm.getStyle('width'));
if(this.im) {
this.im.setAttributes({
src : src,
width : (w && options.image.width) ? Math.min(w, options.image.width) : ''
});
}
}
Change the nicUpload.php like this
<?php
/* NicEdit - Micro Inline WYSIWYG
* Copyright 2007-2009 Brian Kirchoff
*
* NicEdit is distributed under the terms of the MIT license
* For more information visit http://nicedit.com/
* Do not remove this copyright message
*
* nicUpload Reciever Script PHP Edition
* #description: Save images uploaded for a users computer to a directory, and
* return the URL of the image to the client for use in nicEdit
* #author: Brian Kirchoff <briankircho#gmail.com>
* #sponsored by: DotConcepts (http://www.dotconcepts.net)
* #version: 0.9.0
*/
/*
* #author: Christoph Pahre
* #version: 0.1
* #description: different modification, so that this php file is working with the newest nicEdit.js (needs also modification - #see)
* #see http://stackoverflow.com/questions/11677128/nicupload-says-invalid-upload-id-cant-make-it-works
*/
define('NICUPLOAD_PATH', '../images/uploadedImages'); // Set the path (relative or absolute) to
// the directory to save image files
define('NICUPLOAD_URI', '../images/uploadedImages'); // Set the URL (relative or absolute) to
// the directory defined above
$nicupload_allowed_extensions = array('jpg','jpeg','png','gif','bmp');
if(!function_exists('json_encode')) {
die('{"error" : "Image upload host does not have the required dependicies (json_encode/decode)"}');
}
if($_SERVER['REQUEST_METHOD']=='POST') { // Upload is complete
$file = $_FILES['image'];
$image = $file['tmp_name'];
$id = $file['name'];
$max_upload_size = ini_max_upload_size();
if(!$file) {
nicupload_error('Must be less than '.bytes_to_readable($max_upload_size));
}
$ext = strtolower(substr(strrchr($file['name'], '.'), 1));
#$size = getimagesize($image);
if(!$size || !in_array($ext, $nicupload_allowed_extensions)) {
nicupload_error('Invalid image file, must be a valid image less than '.bytes_to_readable($max_upload_size));
}
$filename = $id;
$path = NICUPLOAD_PATH.'/'.$filename;
if(!move_uploaded_file($image, $path)) {
nicupload_error('Server error, failed to move file');
}
$status = array();
$status['done'] = 1;
$status['width'] = $size[0];
$rp = realpath($path);
$status['url'] = NICUPLOAD_URI ."/".$id;
nicupload_output($status, false);
exit;
}
// UTILITY FUNCTIONS
function nicupload_error($msg) {
echo nicupload_output(array('error' => $msg));
}
function nicupload_output($status, $showLoadingMsg = false) {
$script = json_encode($status);
$script = str_replace("\\/", '/', $script);
echo $script;
exit;
}
function ini_max_upload_size() {
$post_size = ini_get('post_max_size');
$upload_size = ini_get('upload_max_filesize');
if(!$post_size) $post_size = '8M';
if(!$upload_size) $upload_size = '2M';
return min( ini_bytes_from_string($post_size), ini_bytes_from_string($upload_size) );
}
function ini_bytes_from_string($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
function bytes_to_readable( $bytes ) {
if ($bytes<=0)
return '0 Byte';
$convention=1000; //[1000->10^x|1024->2^x]
$s=array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB');
$e=floor(log($bytes,$convention));
return round($bytes/pow($convention,$e),2).' '.$s[$e];
}
?>
You can manually pass an id to your script: e.g nicUpload.php?id=introPicHeader and it will become introPicHeader.jpg (or appropriate extension) in the images folder you defined.
However, I have noticed that this script is broken and cannot access the configuration option uploadURI if specified directly in nicEdit.js during the nicEditorAdvancedButton.extend({. This causes access to an relatively pathed "Unknown" resource, causing an error.
The documentation implies otherwise and the fact that the nicURI was specified here for imgur.com (maybe as a default) gave me the impression I could also add a uploadURI reference to the nicUpload.php script in a single place rather than on every editor instantiation.
Update
This works if you pass it during instantiation, which I guess does allow for easy dynamic id population.
Unfortunately, the nicUpload.php is riddled with errors and it's output is not JSON. The editor expects to parse JSON and finds a script tag and errors with unexpected token "<".
There are a raft of other errors which I will attempt to identify:
In nicEdit.js
A.append("image") should be infact A.append("nicImage")
this.onUploaded(D.upload) should become this.onUploaded(D)
this.onUploaded(D) should be moved to within the try block after var D=JSON.parse(C.responseText) to fix variable scope issues
B.image.width needs to become B.width
In nicUpload.php
JSON output is not formed correctly, comment out html output and output just json_encode($status).
JSON output needs to return a key/value pair named links rather than url although renaming the var D=B.links to var D=B.url in nicEdit.js would also suffice as a fix.
Both php and javascript code leaves a lot to be desired, I get many errors regularly and have been fixing them myself.

Resources