فهرست منبع

added FileStorage with working upload binary file

Piotr Labudda 9 سال پیش
والد
کامیت
2bb5af97eb
1فایلهای تغییر یافته به همراه285 افزوده شده و 0 حذف شده
  1. 285 0
      SE/se-lib/Route/FileStorage.php

+ 285 - 0
SE/se-lib/Route/FileStorage.php

@@ -0,0 +1,285 @@
+<?php
+// @requires $_SERVER['SERVER_NAME']
+
+Lib::loadClass('RouteBase');
+Lib::loadClass('Schema_TableFactory');
+Lib::loadClass('Response');
+Lib::loadClass('UI');
+Lib::loadClass('OBJ');
+
+/*
+# FileStorage:
+- [x] create CRM_FILES - sql at the end of file
+  - [x] only meta fields, perms? - no perms in relation based on record which is connected
+- [x] add file to storage - API POST/PUT action
+  - [ ] base storage folder - from config - default /Library/Server/Web/Data/p5-pliki, chmod - add to instalator, upgrade
+	- [x] subfolders like postfix, but [0-9],[A-Z] - substr(strrev(base_convert($id, 10, 10 + 26)), 0, 1) - 36 folderów
+	- [x] file connected to user - A_RECORD_CREATE_AUTHOR
+- [ ] connect file to record - {tbl_name}__REF__FILES
+
+# upload API: `index.php?_route=FileStorage&_task=upload&name={file_name}`
+
+*/
+class Route_FileStorage extends RouteBase {
+
+	public function handleAuth() {
+		if (!User::logged()) {
+			User::authByRequest();
+		}
+	}
+
+	public function defaultAction() {
+		UI::gora();
+		UI::menu();
+		try {
+			echo '...';
+		} catch (Exception $e) {
+			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
+		}
+		UI::dol();
+	}
+
+	public function addFile($content, $name = '') {
+		$rootFileStoragePath = '/tmp/test-upload-file-storage';// TODO: from config!
+
+		$sqlLogin = User::getLogin();
+		$sqlLabel = DB::getPDO()->quote($sqlLabel, PDO::PARAM_STR);
+		$sql = "
+			insert into CRM_FILES (`A_RECORD_CREATE_AUTHOR`,`A_RECORD_CREATE_DATE`,`FILE_LABEL`)
+			values ('{$sqlLogin}', NOW(), {$sqlLabel})
+		";
+		DBG::_('DBG', '>2', "sql", $sql, __CLASS__, __FUNCTION__, __LINE__);
+		DB::getPDO()->exec($sql);
+		$dbLastId = DB::getPDO()->lastInsertId();
+		DBG::_('DBG', '>1', "dbLastId", $dbLastId, __CLASS__, __FUNCTION__, __LINE__);
+		$filePath = $this->generateFilePathHashFromID($dbLastId);
+		DBG::_('DBG', '>1', "filePath", $filePath, __CLASS__, __FUNCTION__, __LINE__);
+
+		$absFilePath = "{$rootFileStoragePath}/{$filePath}";
+		$dirPath = dirname($absFilePath);
+		@mkdir($dirPath, $mode = 0777, $recursive = true);
+		if (!file_exists($dirPath)) throw new Exception("Cannot create path");
+		@chmod($dirPath, $mode = 0777);
+
+		$fp = fopen($absFilePath, 'w');
+		fwrite($fp, $fileContent);
+		fclose($fp);
+
+		if (!file_exists($dirPath)) throw new Exception("Cannot save file");
+	}
+
+	public function uploadAction() {
+		try {
+			$fileContent = Request::getRequestBody();
+			$sqlLabel = V::get('name', '', $_REQUEST);
+			$this->addFile($fileContent, $sqlLabel);
+			echo 'file uploaded';
+		} catch (Exception $e) {
+			echo "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage();
+		}
+	}
+
+	public function uploadFromBinaryTestAction() {
+		try {
+			$fileContent = Request::getRequestBody();
+			$filePath = '/tmp/test-upload-data.txt';
+			$fp = fopen($filePath, 'w');
+			fwrite($fp, $fileContent);
+			fclose($fp);
+
+			echo 'file uploaded?';
+		} catch (Exception $e) {
+			echo "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage();
+		}
+	}
+
+	public function downloadTestAction() {
+		try {
+			$filePath = '/tmp/test-upload-data.txt';
+			if (!file_exists($filePath)) throw new Exception("file not exists!");
+	    header('Content-Description: File Transfer');
+	    header('Content-Type: application/octet-stream');
+	    header('Content-Disposition: attachment; filename="'.basename($filePath).'"');
+	    header('Expires: 0');
+	    header('Cache-Control: must-revalidate');
+	    header('Pragma: public');
+	    header('Content-Length: ' . filesize($filePath));
+	    readfile($filePath);
+	    exit;
+		} catch (Exception $e) {
+			echo "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage();
+		}
+	}
+
+	public function uploadFromFormTestAction() {
+		try {
+			// $fileContent = Request::getRequestBody();
+			DBG::_(true, true, '_POST', $_POST, __CLASS__, __FUNCTION__, __LINE__);
+
+			// $filePath = '/tmp/test-upload-data.txt';
+			// $fp = fopen($filePath, 'w');
+			// fwrite($fp, $fileContent);
+			// fclose($fp);
+
+			// echo 'file uploaded?';
+		} catch (Exception $e) {
+			echo "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage();
+		}
+	}
+
+	public function uploadFormTestAction() {
+		UI::gora();
+		UI::menu();
+		try {
+			// multiple: <input type="file" id="file_input" multiple="multiple" />
+			// only images: <input type="file" id="file_input" multiple="multiple" accept="image/*" />
+			?>
+<div class="container">
+	<form>
+		<input type="file" id="file_input" style="display:block; width:100%; height:200px; background-color:silver; text-align:center">
+	</form>
+	<button class="btn btn-primary" id="upload_file_as_binary_btn">upload as binary</button>
+	<button class="btn btn-default" id="upload_file_as_form_btn">upload as form</button>
+	<a class="btn btn-default" href="index.php?_route=FileStorage&_task=downloadTest" target="_blank">download</a>
+</div>
+<script>
+document.getElementById('file_input').addEventListener('change', function() {
+  for (var i = 0; i < this.files.length; i++){
+    var file =  this.files[i];
+    // This code is only for demo ...
+    console.group("File "+i);
+    console.log("name : " + file.name);
+    console.log("size : " + file.size);
+    console.log("type : " + file.type);
+    console.log("date : " + file.lastModified);
+    console.groupEnd();
+  }
+}, false);
+
+function uploadFileAsForm(file) {
+	var serverUrl = '<?php echo Request::getPathUri() . "index.php?_route=FileStorage&_task=uploadFromFormTest"; ?>';
+  var xhr = new XMLHttpRequest();
+  var fd = new FormData();
+  xhr.open("POST", serverUrl, true);
+  xhr.onreadystatechange = function() {
+    if (xhr.readyState == 4 && xhr.status == 200) {
+      // Every thing ok, file uploaded
+      console.log(xhr.responseText); // handle response.
+    }
+  };
+  fd.append("upload_file", file);
+  xhr.send(fd);
+}
+function uploadFileAsBinary(file) {
+	var serverUrl = '<?php echo Request::getPathUri() . "index.php?_route=FileStorage&_task=uploadFromBinaryTest"; ?>';
+	var serverUrl = '<?php echo Request::getPathUri() . "index.php?_route=FileStorage&_task=upload"; ?>';
+	var _dbg = true;
+
+	// .set('Accept', 'application/json')
+	superagent.post(serverUrl + '&name=' + file.name)
+		.set('Content-Type', file.type)
+		.send(file)
+		.end(function(err, res) {
+			if(_dbg)console.log('DBG: res:', res, 'res.body:', res.body);
+		})
+
+return
+
+  jQuery.ajax({
+    type: "POST",
+    beforeSend: function (request) {
+      request.setRequestHeader("Content-Type", file.type);
+    },
+    url: serverUrl,
+    data: file,
+    processData: false,
+    contentType: false,
+    success: function (data) {
+      console.log("File available at: ", data);
+    },
+    error: function (data) {
+      var obj = jQuery.parseJSON(data);
+      alert(obj.error);
+    }
+  })
+}
+
+jQuery('#upload_file_as_binary_btn').on('click', function() {
+	var fileInput = document.getElementById('file_input')
+	if (!fileInput) return false;// TODO: error msg
+	if (!fileInput.files) return false;// TODO: error msg
+	if (!fileInput.files.length) return false;// TODO: error msg
+	var fileInfo = fileInput.files[0];
+	console.log('fileInfo', fileInfo);
+	uploadFileAsBinary(fileInfo);
+});
+jQuery('#upload_file_as_form_btn').on('click', function() {
+	var fileInput = document.getElementById('file_input')
+	if (!fileInput) return false;// TODO: error msg
+	if (!fileInput.files) return false;// TODO: error msg
+	if (!fileInput.files.length) return false;// TODO: error msg
+	var fileInfo = fileInput.files[0];
+	console.log('fileInfo', fileInfo);
+	uploadFileAsForm(fileInfo);
+});
+</script>
+			<?php
+		} catch (Exception $e) {
+			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
+		}
+		UI::dol();
+	}
+
+	public function generateFilePathHashFromID($intId) {
+		// $base36Id = base_convert($intId, 10, 10 + 26);// 0-9 + A-Z
+		$base36Id = base_convert($intId, 10, 10 + 6);// 0-9 + A-F
+		$base36Str = str_pad($base36Id, 10, "0", STR_PAD_LEFT);
+		$base36Str = strrev($base36Str);
+		$pathParts = array();
+		$pathParts[] = substr($base36Str, 0, 2);
+		$pathParts[] = substr($base36Str, 2, 2);
+		$pathParts[] = substr($base36Str, 4);
+		$hashPath = implode("/", $pathParts);
+		echo "ID($intId) converted to ({$base36Id})\t to ({$base36Str})\t to path ({$hashPath})\n";
+		return $hashPath;
+	}
+
+	public function generatePathTestAction() {
+		try {
+			$start = 0;
+			$start = 446071;
+			$limit = $start + 100;
+			echo '<pre>';
+			for ($i = $start; $i < $limit; $i++) {
+				$this->generateFilePathHashFromID($i);
+			}
+			echo '</pre>';
+		} catch (Exception $e) {
+			echo "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage();
+		}
+	}
+
+}
+
+/*
+
+CREATE TABLE IF NOT EXISTS `CRM_FILES` (
+  `ID` int(11) NOT NULL AUTO_INCREMENT,
+  `FILE_HASH` varchar(255) NOT NULL, -- generated from ID by hash function - only for cache
+  `FILE_LABEL` varchar(255) NOT NULL, -- original file name or system name
+  `FILE_TYPE` varchar(32) NOT NULL DEFAULT '', -- $TRG_FILE -> config/.cnf--folders...
+  `FILE_MTIME` datetime NOT NULL,
+  `A_STATUS` enum('WAITING','NORMAL','MONITOR','OFF_HARD','OFF_SOFT','DELETED') NOT NULL DEFAULT 'WAITING',
+  `A_RECORD_CREATE_DATE` datetime DEFAULT NULL,
+  `A_RECORD_CREATE_AUTHOR` varchar(40) NOT NULL DEFAULT '',
+  `A_RECORD_UPDATE_DATE` datetime DEFAULT NULL,
+  `A_RECORD_UPDATE_AUTHOR` varchar(40) NOT NULL DEFAULT '',
+	`A_ADM_COMPANY` varchar(100) NOT NULL DEFAULT '',
+	`A_CLASSIFIED` varchar(100) NOT NULL DEFAULT '',
+  PRIMARY KEY (`ID`),
+  KEY `FILE_TYPE` (`FILE_TYPE`)
+) ENGINE=MyISAM  DEFAULT CHARSET=latin2;
+
+2016-07-20: 446071 files in /Library/Server/Web/Data/Sites/Default/PLIKI
+
+*/