0

On my network, there is a directory where we have many large images being stored. From my sails app, I would like to be able to show them. The web server is not the same box as the "image store" location. So I would need to show images outside of the assets folder. How can I do this? I don't care if the controller action will manually get the image by filename, or if there is some sort of virtual routing to create a location in the app that points somewhere else. Just need to know how. I couldn't find anything on the webs.

Dave Semar
  • 51
  • 3

2 Answers2

0

Here you have an example of mine. Hope I understood correctly:

attachments: function(req, res) {
  if(req.method === 'GET') {
    var params = req.params.all();
    var filePath = [process.cwd(), '../yourpath/', params.filename].join('/');

    var stat = fs.statSync(filePath);

    var readStream = fs.createReadStream(filePath);
    readStream.pipe(res);
  }
},

Basically you can get the file from whatever path you want. Once you hit /controller/attachments/file.jpg, this function will return the image.

Warning: As stated by @Liam, "This has some serious security risks with ../ in the params.filename as they can now download every file on your server that has global read permissions." So take whatever precautions you need in order to avoid this.

yBrodsky
  • 4,981
  • 3
  • 20
  • 31
  • This has some serious security risks with `../` in the `params.filename` as they can now download every file on your server that has global read permissions. – Liam Gray Mar 13 '17 at 15:48
  • It's a good point. You could sanitize the filename, dunno what else could be done in order to fetch dynamic files. – yBrodsky Mar 13 '17 at 16:11
  • 'fs' isn't defined. – Dave Semar Mar 13 '17 at 16:11
  • var fs = require('fs'). Still, consider what Liam said in the comment above. I have this method accesible only by logged users of a closed system. If you are putting this out for everybody, might need some improvement. – yBrodsky Mar 13 '17 at 16:13
  • Doing a reverse proxy that separates static files from the node instance is the standard way of serving static files. – Liam Gray Mar 13 '17 at 16:28
  • What if you need that only authenticated people see the files? – yBrodsky Mar 13 '17 at 17:13
0

There are two standard ways of doing this. The preferred/more performant way is to set up a reverse proxy to serve your static files (and you can configure different routes for different servers).

Reverse Proxy Method (Preferred)

Apache/Nginx

The preferred would be to have your Apache or nginx reverse proxy configured so that a certain url (say /assets/images/<custom-folder> would serve the directory directly instead of proxying through Nodejs. This is more efficient as the Apache/nginx daemons are far quicker than Node at serving files.

[nginx config example inbound]

IISNode

See question: Serving static files from iisnode with URL Rewrite

I have no experience in setting up IISNode, but from the looks of it, you can have it serve the static files instead of having Sails.js serve the files, that way you can configure different routes for different folders. Below is an example of an IISNode config with static files being served, I'd imagine you can set up multiple static and static-serve rewrite rules for different folders.

<system.webServer>
  <handlers>
    <clear />
    <add name="iisnode" path="/index.js" verb="*" modules="iisnode" />
    <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
  </handlers>
  <rewrite>
    <rules>
      <rule name="static">
        <action type="Rewrite" url="www{REQUEST_URI}" />
      </rule>
      <rule name="serve-static" stopProcessing="true">
        <conditions logicalGrouping="MatchAny">
          <add input="{REQUEST_FILENAME}" matchType="IsFile" />
          <add input="{REQUEST_URI}" pattern="^/www/$" />
        </conditions>
      </rule>
      <rule name="node">
        <action type="Rewrite" url="index.js" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

Symbolic Link Method (Easier)

The other (easier) method is to symlink the folder inside your Sails.js assets directory, and then serve it through the usual Sails.js routes. To set up a symbolic link:

cd <assets-dir>
ln -s <full-path-of-large-images-dir> <folder-name>

For example:

cd assets/images
ln -s /var/images/large large

And then you'll have a folder assets/images/large that points to the /var/images/large directory.

Community
  • 1
  • 1
Liam Gray
  • 1,089
  • 9
  • 16
  • I didn't specify, but we're hosting this on windows iis using iisnode. I have tried using a virtual directory. But sails doesn't see the virtual directory. – Dave Semar Mar 13 '17 at 15:59
  • Edited the answer to include doing a reverse proxy with IISNode – Liam Gray Mar 13 '17 at 16:27