Search code examples
javascriptnode.jsherokupathrelative-path

Heroku nodejs pathing issue... Error: ENOENT: no such file or directory


I have a nodejs application using hapi.js and I'm trying to download an image from a url. Heroku is giving me errors with the pathing.

My code:

Request(uri).pipe(fs.createWriteStream(__dirname+'/../public/images/'+filename)).on('close', callback);

My errors:

 Error: ENOENT: no such file or directory, open '/app/../public/images/1430540759757341747_4232065786.jpg'

My file structure is simple:

app.js
-public
 -images
  -sampleimage.jpg
 -videos
  -samplevideo.mp4
 -audio
  -sampleaudio.wav

As you can see the __dirname for heroku application is /app. I've tried using __dirname+'all sorts of pathing ../ ./ etc' and I've also tried it without __dirname.

I will be creating a lot of these files using ffmpeg and a speech tool. So could anyone explain to me what kind of problem I am having? Is it something that can be solved by using the correct path name or is it my hapijs server configurations that I need to configure?


Solution

  • You just have the wrong path in your project.

    On Heroku, you can't write to the folder BELOW the root of your project.

    In your case, your code is running in app.js, which is in the 'root' folder of your project.

    So, on Heroku's filesystem, this means your project looks like this:

    /app
    /app/app.js
    /app/public
    /app/public/images
    ...
    

    Heroku puts all your code into a folder called app.

    Now, in your code pasted above, you show:

    Request(uri).pipe(fs.createWriteStream(__dirname+'/../public/images/'+filename)).on('close', callback);
    

    If this code is running in your app.js, it means that by going BACK a folder (eg: ..), you're trying to write to a non-writable part of Heroku's filesystem.

    Instead, you want to write to:

    Request(uri).pipe(fs.createWriteStream(__dirname+'/public/images/'+filename)).on('close', callback);
    

    This will correctly write your file into the images folder like you want.

    HOWEVER

    Here's where things are going to get complicated for a moment.

    On Heroku, you can indeed write files to the filesystem, but they will DISAPPEAR after a short period of time.

    Heroku's filesystem is EPHEMERAL, this means that you should treat it like it doesn't exist.

    The reason Heroku does this is because they try to force you to write scalable software.

    If your application writes files to your webserver disk, it won't scale very much. The reason why is that disk space is limited. Each web server has its own disk. This can lead to confusing / odd behavior where each webserver has a copy of the same file(s), etc. It just isn't a good practice.

    Instead: what you should do is use a file storage service (usually Amazon S3) to store your files in a central location.

    This service lets you store all of your files in a central location. This means:

    • You can easily access your files from ALL of your web servers.
    • You can have 'reliable' storage that is managed by a company.
    • You can scale your web applications better.