Binary static resources not downloading

I’ve set up a content type “PPTX”, with extension “.pptx”, mime type “application/vnd.openxmlformats-officedocument.presentationml.presentation”, and set to “binary”. When I add a static resource with this content type, the file doesn’t download; I just get a file with the right title but no content. If I turn off “binary”, then content does get downloaded, but of course it’s gibberish.

Using MODX 3.0.4.


UPDATE:
after monkeying around with the PPTX content type, now PDFs aren’t downloading either! Just blank content. I didn’t touch the PDF content type. So, both content types set to “binary” are not downloading.

Can you reproduce this issue on a fresh MODX installation?

My first guess would be, that there’s a plugin (on an event like OnWebPagePrerender or OnLoadWebDocument) that maybe does some string replacement and doesn’t discern between binary and non-binary output.

I tried adding PPTX on another site, and it works fine. These are the plugins on the problematic site:

Ace
ClientConfig
Collections
Colorpicker
Fox Tree Sorting
Guzzle7
Image+
Login
MIGX
pdoTools
pThumb
Resizer
SiteDashClient
StageCoach
Tagger
TinyMCE Rich Text Editor
UltimateParent
UpgradeMODX
VersionX

Those are pretty much the same plugins I use on the other site, with a few differences. I disabled one custom plugin that was running OnBeforeDocFormSave, but that didn’t make any difference. I also change the file names of the linked files so that there are no spaces in them, and that didn’t matter either.

The event OnBeforeDocFormSave only runs in the manager. If a plugin is the problem, then it has to run on an event that gets invoked for frontend requests.

Yes, AFAIK no plugins are doing that. What’s mystifying is that the PDF static resource was working fine until I added the PPTX content type.

I tried turning off the custom plugin because it alters the content field on saving, and since static file links are stored in the content field, I wanted to rule out changes to this field causing an issue.

More weirdness. When I upload a file to the assets directory through a media source from the static resource field, rather than go in the folder I have open, MODX creates a bunch of new folders, duplicating the path to the folder I already have open. So, I edited a static resource that was linked to a file in the Documents media source (path: assets/media/documents/arngh), uploaded a new file to the images folder (path: assets/media/images), and this happened:

Screen Shot 2024-02-22 at 10.04.56 AM

The same thing happened when I initially uploaded a PDF to the Documents folder. So I get doubled paths (like “assets/media/documents/assets/media/documents/arngbh/filename.pdf”).

I was able to reproduce the issue with the duplicated file paths.
I will look into it to see if I can find the problem.


This seems to be unrelated to the inital problem though.
If MODX can’t find the file (selected in the static resource), then you get redirect to the error page on the frontend and there’s an error message in the log (“modStaticResource->getFileContent() for resource xx: Could not load content from file …”)

I opened a issue for this on Github:

For now, after you changed the media source, click the root node of the source (see image) in the tree to make it the active node before uploading files. This should avoid the issue.

media_browser

Regarding the original issue: To output the content of a static resource, MODX runs the function getFileContent() (of the class MODX\Revolution\modStaticResource).

You could try to “debug” this function to maybe better understand what’s going wrong.


You could for example add the line

$this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "filesize of {$this->_sourceFile} is {$filesize}");

after these lines of code

to log the file-size to the MODX error log.


The code uses the function readfile to read the file content. The return value is “the number of bytes read from the file on success, or false on failure”.

You could change the line

to

$result = readfile($content);
$this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "result of readfile = {$result}");

to log “the number of bytes read” to the MODX error log.

I added those new lines of code to the modStaticResource.php file.

I had set up a template called “static resource” so that I could use form customization to get rid of all fields except pagetitle and content for easy editing. This template is completely blank (no content).

  1. If I make a new static resource, select either “standard page” or “(empty)” for the template, enter the linked file, and set the content type to either PDF or PPTX, then save it, the download works fine, and the log records the file size with the code I added to modStaticResource.php.

  2. If I change this resource to the “static resource” template, it stops working, and nothing is entered into the log.

  3. If I change the resource back to the “standard page” template, it still doesn’t work.

  4. If I add just “[[*content]]” to the “static resource” template, then download starts working for static resources assign to this template.

So, what’s the difference between a blank template and selecting “(empty)” for the template?

Regarding no. 3, it seems like templates that have uncached content tags make static resource downloading fail, and ones without it do not, even if the content is being created with a snippet instead of a simple [[*content]] tag. So “[[!*content]]” and “[[!contentsnippet]]” fail, but “[[*content]]” and “[[contentsnippet]]” do not.

Selecting (empty) as the template means “no template is assigned”. If MODX processes a resource with no assigned template, then the code just outputs the content.

If however a template is assigned to the resource, then the MODX parser processes the template and returns the result. If the assigned template is empty, then nothing gets returned.

I think you must mean if the template has no “content” field, then nothing gets returned (at least in the case of static resources). No matter how much code I put in the static resource template, if the content field isn’t in there in some form, nothing gets returned. But ALSO, the content field has to be cached, not un-cached (regardless of whether the resource setting “cacheable” is on or off).

It’s surprising to me, because I would have thought that MODX would know that a static resource needs no template, since it’s just outputting a file rather than rendering HTML.

The point of a static resource is to return the content of a file. If you want to do elaborate stuff in the template, then don’t use a static resource.

Static resources don’t get cached. They just return the content of the linked file.
If you put uncached tags into the template, you just break the process.

My point is that static resources should just ignore the template altogether, since they only return external files. Why should I need to put anything at all in the template? It’s completely non-intuitive. If someone makes a static resource, it’s going to be assigned whatever the default template is. If that template has a non-cached content field, the output is going to be broken, and no one will know why unless they read this thread!

Curiously, weblinks do NOT get broken if you assign them to an empty template, even though the link is in the Content field, just like static resources. So they are ignoring the template. Shouldn’t static resources work the same way?

I’ve entered a bug report/feature request (not sure which this would be) concerning this.

Let’s remember that what we are discussing here are only static resources with binary content.

If the output is not binary, then the static resources behave like normal resources. They are cached, the template is part of the output, you can use uncached tags etc.


So what you are complaining about here, is that you can’t use the “default template” (that contains HTML tags) for your binary static resource. But you (obviously) also don’t want the HTML markup of the template to be part of the output.

To me it’s debatable if this is a MODX bug or merely a user input error.
If you only want the binary file in the output, don’t assign a template to the static resource. If you (for some reason) need a template, use a dedicated one that only contains a [[*content]] tag.

My point is that binary files will never use an HTML wrapper or anything else associated with a template, so output shouldn’t fail; output should just ignore the assigned template altogether. Doesn’t that make sense? It’s bizarre to me that [[*content]] is needed in a template assigned to a binary static resource, because as far as I can tell, I can fill up a template with all sorts of code, and none of it affects the output of a binary file at all. So why does “[[*content]]” have to be in there? It just makes no sense logically.

AND, if the static resource is not binary, say a text file, and resource type is text, and I assign a custom template that is completely blank (doesn’t have [[*content]]) in it, that works just fine. Why does a non-binary static resource not need [[*content]], but a binary one does??? Even a static resource of type HTML outputs the linked file when assigned a completely blank template.

Also, the MODX Docs on static resources says this:

If you need to add some meta information to the resource via some Template Variables, and you create your own ‘empty’ template to enable this, then you must set the contents of the template to [[*content]] before it will work correctly.

If “[[*content]]” is the only text in the custom template, how would TVs have any effect on it?

And note that it doesn’t say anything about binary files not loading at all if “[[*content]]” isn’t in your template, only that you need this if you’re using TVs for something.

If there is actually no way to change how this works, or some reason this has to stay the way it is (please tell me why!), then it would be good to update the MODX Docs to specify that [[*content]] is needed in any template, using TVs or not, for binary static resources.

Yes, as I mentioned above, I have to set up a specific template in order to use form customization to remove fields unrelated to how the binary static resource works, like long_title and description for example.

I wouldn’t have gotten into this dilemma if I hadn’t wanted to use form customization for my binary static resources, and if my regular template didn’t have a non-cached content field. I often want different layouts for different resources, even ones that use the exact same template code, so it’s a little funky that we have to create new templates just to be able to add custom layouts. It sure would be nice to be able to have layouts that aren’t tied to just one specific template. But that’s a whole other can of worms … ! :wink:

And, FYI, I’m not just “complaining”. I’m:

  1. Trying to understand better how MODX works at the programming level.

  2. Suggesting improvements that I think would make for better user experience, greater efficiency, and/or less hair-pulling.