Questions and discussion about using ProcessMaker 2: user interface, running cases and functionality
Forum rules: Please search to see if a question has already been asked before posting. Please don't ask the same question in multiple forums.
#784292
We need to download all output documents to our computer. PM GUI only allows to download one file at a time.

1. Is there any other way to download those files?
2. Where can we find output documents on FTP? Could you let us know the path? The files need to be download as it is shown on the index list on processmaker. Screen shot is attached.

Thank you for your help in advance!
Suzanne
Attachments
Projects-File.png
Projects-File.png (62.12 KiB) Viewed 14392 times
#784295
It is not possible to download multiple files as you are requesting at once.

The files are located at /<processmaker-installation-directory>/shared/sites/<workspace-name>/files.
However, the files/folders will be meaningless because they are stores with the APP_UID, a 32 character hashed string. The meta data is stored in the database and is dynamically added to the file when it is downloaded via the ProcessMaker GUI.

If you want to create the ability to download multiple files at once and still retain the correcting and of everything, perhaps in a nice zipped file, I would suggest looking at our plugin platform.
By quipper8
#784350
Yeah, you can do it. Here is a little script to export the processmaker filesystem into something normal. It is meant to run from command line on same machine where processmaker is, but you could modify to run however.

USAGE extract_pm_fs.php WORKSPACE TARGET_DIR

you should extract to someplace you can access it...

for example

php /usr/local/bin/extract_pm_fs.php workflow /sharedstorage0/files/workflow/

Code: Select all
<?php

#by quipper8 on forum.processmaker.com
#no copyright, have fun, don't get hurt
#note this makes no distinction between input or output documents, perhaps could add another element to query for APP_DOC_TYPE if needed

#init variables

#php command line first argument should be workspace to export files for, usually default is workflow
$workspace=$argv[1];

#php command line script second argument should be the target directory. don't get wacky with spaces and specical chars
$targetdir=$argv[2];

#TODO add help arg if default args are not included

$servername = "localhost";
$username = "root";
$password = "yourpassword";
$dbname = "wf_" . $workspace;

/* SCHEMA of pm tables queried

--
-- Table structure for table 'APP_FOLDER'
--

CREATE TABLE APP_FOLDER (
  FOLDER_UID varchar(32) NOT NULL DEFAULT '',
  FOLDER_PARENT_UID varchar(32) NOT NULL DEFAULT '',
  FOLDER_NAME mediumtext NOT NULL,
  FOLDER_CREATE_DATE datetime NOT NULL,
  FOLDER_UPDATE_DATE datetime NOT NULL,
  PRIMARY KEY (FOLDER_UID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Folder System PM Documents';


--
-- Table structure for table 'APP_DOCUMENT'
--

CREATE TABLE APP_DOCUMENT (
  APP_DOC_UID varchar(32) NOT NULL DEFAULT '',
  DOC_VERSION int(11) NOT NULL DEFAULT '1',
  APP_UID varchar(32) NOT NULL DEFAULT '',
  DEL_INDEX int(11) NOT NULL DEFAULT '0',
  DOC_UID varchar(32) NOT NULL DEFAULT '',
  USR_UID varchar(32) NOT NULL DEFAULT '',
  APP_DOC_TYPE varchar(32) NOT NULL DEFAULT '',
  APP_DOC_CREATE_DATE datetime NOT NULL,
  APP_DOC_INDEX int(11) NOT NULL,
  FOLDER_UID varchar(32) DEFAULT '',
  APP_DOC_PLUGIN varchar(150) DEFAULT '',
  APP_DOC_TAGS mediumtext,
  APP_DOC_STATUS varchar(32) NOT NULL DEFAULT 'ACTIVE',
  APP_DOC_STATUS_DATE datetime DEFAULT NULL,
  APP_DOC_FIELDNAME varchar(150) DEFAULT NULL,
  PRIMARY KEY (APP_DOC_UID,DOC_VERSION),
  KEY indexAppDocument (FOLDER_UID,APP_DOC_UID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Documents in an Application';


*/

	function foldersize($path) {
		$total_size = 0;
		$files = scandir($path);
		$cleanPath = rtrim($path, '/'). '/';

		foreach($files as $t) {
			if ($t<>"." && $t<>"..") {
				$currentFile = $cleanPath . $t;
				if (is_dir($currentFile)) {
					$size = foldersize($currentFile);
					$total_size += $size;
				}
				else {
					$size = filesize($currentFile);
					$total_size += $size;
				}
			}   
		}

		return $total_size;
	}
	
	
	function mycopy($s1,$s2) {
	
		$path = pathinfo($s2);
		if (!file_exists($path['dirname'])) {
			mkdir($path['dirname'], 0777, true);
		}   
		if (!copy($s1,$s2)) {
			echo "copy failed \n";
    }
}
	
	
		# /opt/processmaker is hard coded, chage if needed
		$du = foldersize("/opt/processmaker/shared/sites/". $workspace . "/files");
		$df = disk_free_space("$targetdir");
		
		print "disk usage of $workspace is $du \n";
		print "disk free of $targetdir is $df \n";
				
		#TODO add some failure if not enough space
				
				
				
				


		#Create connection to DB
		
		print "connecting to workspace database $dbname \n";
		
		$conn = new mysqli($servername, $username, $password, $dbname);
		
		// Check connection
		if ($conn->connect_error) {
		die("Connection failed: " . $conn->connect_error);
		}else{
		print "Connected db successfully \n";
		}
		
		#get the folder paths as they are in database and as they should be in a filesystem
		
		$sql_getpaths="SELECT CONCAT('/', t3.FOLDER_NAME, '/', t2.FOLDER_NAME, '/', t1.APP_DOC_FIELDNAME) AS targetfile, CONCAT('/', t1.APP_UID, '/', t1.APP_DOC_UID) as sourcefile
						FROM APP_DOCUMENT AS t1
						LEFT JOIN APP_FOLDER AS t2 ON t2.FOLDER_UID = t1.FOLDER_UID
						LEFT JOIN APP_FOLDER AS t3 ON t3.FOLDER_UID = t2.FOLDER_PARENT_UID
						WHERE t2.FOLDER_UID IS NOT NULL and t2.FOLDER_NAME IS NOT NULL and t3.FOLDER_NAME IS NOT NULL";
				  
		print "Translating filepaths from db to fs\n";
					
		$result_getpaths = $conn->query($sql_getpaths);
			if (!$result_getpaths) {
				die('Could not connect: ' . mysql_error());
				}else{
				print "Got filepaths OK \n";
				}

				while($row = $result_getpaths->fetch_assoc()){
							
							$sourcefile="/opt/processmaker/shared/sites/" . $workspace . "/files" . $row['sourcefile'];
							$targetfile=$targetdir . $row['targetfile'];
							
							$sourcefilesearch=$sourcefile . "*";
							
							$all_source_versions=glob($sourcefilesearch);
							
							
							
							foreach($all_source_versions as $filename){
								$sourcepath=pathinfo($filename);
								$sourcefile = $filename;
								$sourcefile_extension= $sourcepath['extension'];
								$targetfile = $targetfile . "." . $sourcefile_extension;
								
								print "copying Source = $sourcefile \n TO \nTarget = $targetfile \n\n";
								mycopy($sourcefile, $targetfile);
							}
						
					}
					


		
$conn->close();

		
?>
By rcordeiro
#784570
Hi,

I changed your code, basically the MySQL. This works for ProcessMaker 2.5, don't know about version 3.
With your SELECT you only get some files, not the ones with the original names from CONTENT table, the ones you get from:
Code: Select all
SELECT * FROM wf_AT.CONTENT
where CON_CATEGORY = 'APP_DOC_FILENAME'
I just changed the SQL SELECT to match all the files, this suits my case but it might need some tweaking to suit all situations:
Code: Select all
select 	concat('/',folder1.FOLDER_NAME,'/',contents.CON_VALUE) as targetfile, 
		concat('/',documents.APP_UID,'/outdocs/',documents.APP_DOC_UID) as sourcefile
	from APP_DOCUMENT as documents
	left join APP_FOLDER as folder1 on folder1.FOLDER_UID = documents.FOLDER_UID
	left join CONTENT as contents on contents.CON_ID = documents.APP_DOC_UID
	where folder1.FOLDER_UID is not null and contents.CON_VALUE != ''
		and folder1.FOLDER_NAME != 'whatever folder you want to remove from the query'
union
select 	concat('/',folder2.FOLDER_NAME,'/',folder1.FOLDER_NAME,'/',contents.CON_VALUE) as targetfile, 
		concat('/',documents.APP_UID,'/',documents.APP_DOC_UID) as sourcefile
	from APP_DOCUMENT as documents
	left join APP_FOLDER as folder1 on folder1.FOLDER_UID = documents.FOLDER_UID
	left join APP_FOLDER as folder2 on folder2.FOLDER_UID = folder1.FOLDER_PARENT_UID
	left join CONTENT as contents on contents.CON_ID = documents.APP_DOC_UID
	where folder2.FOLDER_UID is not null and folder1.FOLDER_UID is not null and contents.CON_VALUE != ''
		and folder2.FOLDER_NAME != 'whatever folder you want to remove from the query'
union
select 	concat('/',folder3.FOLDER_NAME,'/',folder2.FOLDER_NAME,'/',folder1.FOLDER_NAME,'/',contents.CON_VALUE) as targetfile, 
		concat('/',documents.APP_UID,'/',documents.APP_DOC_UID) as sourcefile
	from APP_DOCUMENT as documents
	left join APP_FOLDER as folder1 on folder1.FOLDER_UID = documents.FOLDER_UID
	left join APP_FOLDER as folder2 on folder2.FOLDER_UID = folder1.FOLDER_PARENT_UID
	left join APP_FOLDER as folder3 on folder3.FOLDER_UID = folder2.FOLDER_PARENT_UID
	left join CONTENT as contents on contents.CON_ID = documents.APP_DOC_UID
	where folder3.FOLDER_UID is not null and folder2.FOLDER_UID is not null and folder1.FOLDER_UID is not null and contents.CON_VALUE != ''
For this part:
concat('/',documents.APP_UID,'/outdocs/',documents.APP_DOC_UID) as sourcefile
the 'outdocs' is because the generated docs are saved under the folder 'outdocs'.

If you have several processes like me, and all of them save files you might do some tweaking to remove folders:
and folder1.FOLDER_NAME != 'whatever folder you want to remove from the query'

Please feel free to comment and improve the script.
By quipper8
#784603
Cool deal.

Good tweaks.

Yes, It will take a little bit of tweaking depending on individual use cases how you want your process structure reflected in a real file structure.

It would be even better for the someone to write a sabredav backend for the pm database so we could access over webdav and also use the inbuilt permissions.

A 1xbet clone script is a pre-designed software so[…]

4rabet clone script is enabling entrepreneurs to e[…]

Parimatch clone script is enabling entrepreneurs t[…]

In the world of cryptocurrency, a wallet is an app[…]