AjaxUpload with individual directory

Hi all. I try to build a form for applications. Users should upload one or more files as an attachment. These files should be stored in the file directory separated by the uploader’s names.

Formit works great with AjaxUpload with a static path to the upload directory. If the directory doesn’t exist, it will be created.

Now I want to create an upload path with the name of the uploader like

&ajaxuploadTarget=`uploads/[[+name]]`

This doesn’t work.

Any ideas to realize this? Many thanks in advance.
For all forum users: happy holidays!

What exactly is the placeholder [[+name]] and where is it set?


I guess that if you want to use a placeholder value for a property in the [[!FormIt? ...]] snippet tag, you have to make sure that the placeholder is set, before FormIt is called.

For example by first executing a custom snippet that sets the placeholder:

[[!setNamePlaceholder]] <!-- custom snippet that sets the 'name' placeholder -->
[[!FormIt?
    ...
    &ajaxuploadTarget=`uploads/[[!+name]]`
    ...
]]

If you have pdoTools (or fastField) installed, then maybe you could also use [[!#post.name]] instead of the placeholder.

Alternatively you could write a custom hook, that runs after the “AjaxUpload2Formit” hook and moves the files to a different directory.

Sorry, more input now.

I have a formit form with a (required) name field, an email field and a message field. Additionally the upload button via AjaxUpload for PDFs.

The formit call is:

[[!FormIt?
  &preHooks=`Formit2AjaxUpload`
  &hooks=`AjaxUpload2Formit,email,redirect`
  &ajaxuploadFieldname=`upload`
  &ajaxuploadTarget=`uploads/[[+name]]/`
  &ajaxuploadUid=`upload`
  …
  <form action= …
  …
    <p>
	<label for="name">Name<strong>*</strong>[[!+fi.error.name:notempty=`<span class="error"> bitte ausfüllen</span>`]]</label>
	<input type="text" id="name" name="name" value="[[!+fi.name]]">
  </p>
  …
  </form>

And I want to get the sub directory for uploads created by the name of the sender after submitting the form. So I can handle all applications separately.
I think, I need a custom hook … but how??

I tried the placeholder [[+name]] like described above but this creates endless sub directories named [[+name]] and not a single directory with the real name of the name fields content.

In this post: Formit setting from input fields there is an example for the formit call with

&emailFromName=`[[+firstname]] [[+lastname]]`

Seems identically like my

&ajaxuploadTarget=`uploads/[[+name]]/`

Maybe the AjaxUpload itself has issues with this placeholder and can’t handle it this way??

The MODX parser parses nested tags first. In this case it means that [[+name]] is processed before the snippet FormIt is called.

So you have to make sure that this placeholder is set beforehand. Either by calling a custom snippet above the FormIt tag (that reads the value from $_POST and sets the placeholder → $modx->setPlaceholder(...)) or by using &ajaxuploadTarget=`uploads/[[!#post.name]]/` instead (if pdoTools is installed).


If the MODX parser can’t find the “name” placeholder, then FormIt is called with the unparsed property value. And AjaxUpload doesn’t parse this property value, before it is used to create the folder.

This is somehow insecure, since name can contain slashes and dots which allows changing the folder. Better add an own hook, that restricts the name and sets the folder by $hook->formit->config for the AjaxUpload hook.

YES! That works. And now I can try to “clean” the input in the name field to avoid security issues.
At this time it’s all a test. The goal is an application form for a gallery. Artists should apply for an exhibition and submit examples of their work in PDF format. Staff at the gallery will then have access to the applications and examples via protected access.

Thanks for this advice. Do you have an example of how this can be implemented? I’m a very low level programmer … sorry.

You have to create a snippet with something like this, and call this snippet in the hooks before AjaxUpload2Formit:

$values = $hook->getValues();

// replace slashes, double dots and use filterPathSegment 
$name = $modx->filterPathSegment(str_replace(['/', '..'], '-', $values['name']));

hook->formit->config['ajaxuploadTarget'] = 'uploads/' . $name . '/';

return true;

You can also set some options for filterPathSegment. The options are shown in the method in the modResource class.

1 Like

Many thanks, that’s very helpful … and I understand it! :smile:

This topic was automatically closed 2 days after discussion ended and a solution was marked. New replies are no longer allowed. You can open a new topic by clicking the link icon below the original post or solution and selecting “+ New Topic”.