Download multiple files at once ; keeping file names after review step

Context : OJS 3.1.2-4

  1. Is there a simple way to download all the Production Ready Files at once? It looks like the reviewer must pick each file one by one for download.

  2. Also I have this journal, that have specific naming convention (as well as practices of dividing the main text file into several sub-files) for how their copyeditors must name files (e.g. “main text-part1”, “main text-part2”, “bibliography”, “figures-legends”, etc) at the copyediting stage, so the layout editor will know where to put those parts and/or format those different parts in their journal design/layout (BTW they use a single OJS article component for those different parts, that is “article text”). However it seems (if I’m correct) that passed the review stage, and once, of course, the article is accepted, the copyediting and production steps will apply the same “anonymisation” rules regarding files names when one needs to download the file. Hence what was uploaded as, let say, “main text-part1.doc” at the copyediting stage will end up, as something like “117-Article Text-415-1-11-20200716.doc” once downloaded by the production/layout editor. I’m not sure I understand why file name anonymisation persists after the review step but notwithstanding, I would like to know if there is a way (direct or workaround maybe) to keep those meaningful file names once review step is completed.

Thank you,

Marie-Hélène Vézina
Université de Montréal

Hello Marie-Helene,
I strongly support your query (and obviously I don’t have a solution, as this is the way the system behaves). I find it not only risky but very annoying: after years of working on consolidating a file naming convention we find it disrupted by the system…
Same applied to files available to readers once articles are published.
Sorry to be able to just share your concern…
Lucia
AboutScience
Milan (Italy)

1 Like

Hi all,

Where are you downloading files from that’s providing the server-side (generated) filenames instead of the filename used on the uploader’s computer? Since issue #2003 I think it should be using the uploader’s computer’s filename.

(We’ve bounced back a bit on this over the years – generally users seem happy keeping client-side filenames, but that can cause confusion when a file is edited and uploaded without a change to the filename to note the revision, e.g. increasing a number. But that seems to be a lesser evil.)

Regards,
Alec Smecher
Public Knowledge Project Team

I am sorry, I meant :
Is there a simple way to download all the Production Ready Files at once? It looks like the production/layout editor must pick each file one by one for download.

Hi all,

Just to keep the thread informative, here’s another issue discussing download filenames: Improve Filename Conventions for Downloaded Files as Part of Submission · Issue #4957 · pkp/pkp-lib · GitHub

As for downloads of all files, that’s requested here (and provisionally filed against OJS/OMP/OPS 3.3.1): [OJS] Add "Download all files" option to all submission grids · Issue #2630 · pkp/pkp-lib · GitHub

Regards,
Alec Smecher
Public Knowledge Project Team

1 Like

Bonjour Alec,

Seems to me that it’s always the system (generated) filename that is offered when one (editor, copyeditor, production/layout editor) wants to download and save a file locally. Never is the filename used on the uploader’s computer offered (or is there a configuration setting I might haved missed?).

Here are screen captures I just did with the demo testdrive (OJS 3) for the case aforementionned (#2).

Copy editor account: copy editing done :
image

Then those 3 files are sent to production; Layout editor account.
When layout editor wants to download files, proposed “save as” file name is the system generated filename :
image


However after having read the thread you cited (Improve Filename Conventions for Downloaded Files as Part of Submission · Issue #4957 · pkp/pkp-lib · GitHub) I can see that it might be usefull to also have those informations generated by the system (Submission #, Content Type, File Submission Number for the server,Version Number, Date) for proper management of multiple articles. Maybe a concatenation of those 2 parts, i.e. server-side-generated + client’s computer name when file was uploaded, at least for non-review steps, would provide some solution for various needs (although it might result in long names)? Something like :
968-Article Text-1377-1-11-20200722_[Partie1_revisee].txt ?

Thank you,

Marie-Hélène V.

Hi @Marie-Helene,

Digging into this a little further:

Download filenames for single files

It turns out you’re right – we are always using filenames generated by the system for workflow file downloads. I’m sure we’ve gone back and forth on this a few times over the years, and it’s one of those things where nobody is happy with either decision :slight_smile:

In order to change from the server-side filenames to the original upload filenames, you’d need to make a slight modification to controllers/api/file/FileApiHandler.inc.php:

diff --git a/lib/pkp/controllers/api/file/FileApiHandler.inc.php b/lib/pkp/controllers/api/file/FileApiHandler.inc.php
index a33d5c70e..e5faa64ab 100644
--- a/lib/pkp/controllers/api/file/FileApiHandler.inc.php
+++ b/lib/pkp/controllers/api/file/FileApiHandler.inc.php
@@ -79,7 +79,7 @@ class FileApiHandler extends Handler {
 		assert(isset($submissionFile)); // Should have been validated already
 		$context = $request->getContext();
 		$fileManager = $this->_getFileManager($context->getId(), $submissionFile->getSubmissionId());
-		if (!$fileManager->downloadById($submissionFile->getFileId(), $submissionFile->getRevision(), false, $submissionFile->getClientFileName())) {
+		if (!$fileManager->downloadById($submissionFile->getFileId(), $submissionFile->getRevision(), false, $submissionFile->getOriginalFileName())) {
 			error_log('FileApiHandler: File ' . $submissionFile->getFilePath() . ' does not exist or is not readable!');
 			header('HTTP/1.0 500 Internal Server Error');
 			fatalError('500 Internal Server Error');

I can see 3 courses of action:

  • Keep our current practice, which doesn’t help you,
  • Change to client-side filenames (or some combination of the two), which would disrupt existing users who are fine with the current filenames,
  • Add a field to Setup somewhere allowing users to specify the filename patterns,
  • Document this on the forum as a potential local modification :slight_smile:

The most general solution would be to add a configuration field. The only downside is that gradually the set of these fields increases, and eventually we’re left with a very overloaded setup UI.

Downloading multiple files at once

Looking into this further, there already is a feature that adds this to certain lists of files. It requires you to have either the ZipArchive extension installed in your PHP environment, or to have configured a tar tool in your config.inc.php configuration file. Currently it’s only enabled on the Submission stage, though. You can add support for this to the Production Ready list by making a small code change described here. (This will be released in the next OJS, either 3.2.1-2 or 3.3.0.)

Regards,
Alec Smecher
Public Knowledge Project Team

1 Like

Thank you @asmecher for this very detailed and very clear answer.

Download filenames for single files

Substitution of getClientFileName() by getOriginalFileName() works well indeed.

For the sake of consistency (if anyone stumble on this post with similar needs), I also changed the downloadAllFiles function in the same way so the zip will contain files with original nomenclature as well :

	function downloadAllFiles($args, $request) {
		// Retrieve the authorized objects.
(...)
		foreach ($submissionFiles as $submissionFile) {
			// Remove absolute path so the archive doesn't include it (otherwise all files are organized by absolute path)
//			$filePaths[str_replace($filesDir, '', $submissionFile->getFilePath())] = $submissionFile->getClientFileName();
				$filePaths[str_replace($filesDir, '', $submissionFile->getFilePath())] = $submissionFile->getOriginalFileName();
		}

However when using getOriginalFilename(), if the filename is edited via the UI and changed (say “abc.docx” for “abcdefg.docx”):

image

this new name is not sent when donwloading:

image

I would not want an editor to edit the file name at the pre-review stage thinking that it would then be anonymized… Is there a way to prevent this?

After giving it some thought, I finally went for an “hybrid” pattern by introducing a getCustomClientFileName() function that picks
client parts (SubmissionId + FileId + RevisionId + timestamp) concatenated with original name
in \lib\pkp\classes\submission\SubmissionFile.inc.php (on a side note: I am glad I insisted on taking a multi-instances approach for our OJS deployment/set-up (i.e. 1 OJS instance per journal), that way I can better customized on a per journal basis, e.g. this function):

	/**
	 * MHV_20200727 -- Get the filename that should be sent to clients when downloading.
	 * @return string
	 */
	function getCustomClientFileName() {
		// Generate a human readable time stamp.
		$timestamp = date('Ymd', strtotime($this->getDateUploaded()));

		$genreDao = DAORegistry::getDAO('GenreDAO');
		$genre = $genreDao->getById($this->getGenreId());

		// Make the file name unique across all files and file revisions.
		// Also make sure that files can be ordered sensibly by file name.
		return	$this->getSubmissionId() . '-'.
			// ($genre? ($genre->getLocalizedName() . '-'):'') .
			$this->getFileId() . '-' .
			$this->getRevision() . '-' .
			// $this->getFileStage() . '-' .
			// $timestamp .
			$timestamp . '-' .
			//'.' .
			//$this->getExtension();
			$this->getOriginalFilename(); // MHV_20200727 : Original file name contains the "." + extension 
	}

Did I forget to consider other important aspects? Is there a risk to run into problems by doing this?

One last question if I may : I see that the original getClientFileName function is also called from classes/services/GalleyService.inc.php and classes/file/SubmissionFileManager.inc.php.
I think I can leave the former as is but I am not sure whether I should change or not the downloadById function within the latter file by swaping the getClientFileName for my custom function?

Downloading multiple files at once

Thank you. I was able to backport the fix to my 3.1.2-4 instance. Works perfectly.

Marie-Hélène V.
Université de Montréal

Hi @Marie-Helene,

We’ve been talking a bit about this internally, and think we’ve lined up some clearer steps starting with the 3.3 release (due for the 4th quarter this year) that’ll be well aligned with what you’re looking for – better use of the uploader’s filename, and some clarity to avoid confusion between the filename and “name” metadata field. Fortunately we had already scheduled some work on the file upload process and this dovetails nicely with it. If you’re able to stick with it until Q4, I’d suggest watching for improvements then. (We’re also planning to publish a release candidate for OJS 3.3 in Q3, so if you’re interested and able to test it then, your feedback would be welcome!)

Regards,
Alec Smecher
Public Knowledge Project Team

2 Likes