Force downloads

Is there any way to force downloads on files served by parse? Basically I want to extend the /parse/files/:appId/:filename route to add a custom header that forces a download, but I can’t find an easy way to do that.

I ended up writing a separate endpoint that essentially does response.end(await fileObject.getData()), but my files are in S3 and this takes a while. But I’m guessing it downloads the whole file locally first and only then starts sending data to the client browser, which is very unresponsive.

Have you tried to use the directAccess option? It will make the client to download directly from s3 and not pass through your server at all.

Unfortunately directAccess will avoid any grant checks and it’s a global option that affects the entire applications. I need something a little more fine grained than that.

So the file will have to pass through your server, what will probably reduce the performance (in comparison to direct access to s3). What you can try to do to speed is, instead of awaiting the whole file to be download before starting the transfer to the client, is create a stream to send file while it is still being received.

1 Like

What you could also consider is a CDN. It will save you costs, decrease download times for clients if you distribute the files in multiple geo-regions and they are usually highly configurable, allowing you to add various headers conditionally, manage streaming or do even image processing on the fly.

1 Like

Is there a way to get access to the file adapter data given a Parse.File object?

I believe there was a PR relating changing the headers / adding application/octet-stream to the file get route.

1 Like

@dblythy it seems that @brunobg’s question could also be solved with your suggested a beforeGetFile trigger.

@brunobg Do you want to open a Parse Server issue to suggest a feature for a beforeGetFile trigger where you can set custom HTTP headers for the file response?
So there is already a FR for that it seems: beforeGetFile trigger · Issue #6572 · parse-community/parse-server · GitHub

1 Like

Thank you for the suggestions and the FR! But what about this, any way to access the adapter directly so I can work around meanwhile?

What do you mean by file adapter data? You can access the storage adapter from within Cloud Code and maybe override the getUrl method that generates the URL, if that helps.

I want to get access to the S3 data so I can access it directly, when all I have is the Parse.File object that I got from myBaseObject.get('myfile'). Here’s some pseudo code of what I want to do:

const myFile = myBaseObject.get('myfile');
const s3Url = myFile.getS3Adapter().getUrl();
const downloadUrl = s3Url + '&request-content-type="application/force-download"';

Thank you!

const ServerConfig = require('../node_modules/parse-server/lib/Config');
const config = ServerConfig.get(Parse.applicationId);
const adapter = config.filesController.adapter;
const url = adapter.getFileLocation(config, “example.txt”);