1

I'm trying to upload images to my Phoenix app on Heroku. I have a simple app that follows the instructions for file uploading from Phoenix's docs.

I have a simple form and the controller uses File.cp_r() to copy the file from the temp directory.

  def create(conn, %{"user" => user_params}) do
    if upload = user_params["photo"] do
      File.cp_r(upload.path, "priv/static/images/foo.jpg") #non-dynamic name, doens't matter
    end
    ...
  end

Works just file on my local. However when I upload this to Heroku, test the form and heroku run find on the directory, I don't see anything.

I have noticed that this directory on heroku has a seemingly forbidding privilege:

drwx------ 2 u25619 dyno 4096 Apr 23 05:14 images

I tried slipping in a nice little File.chmod("priv/static/images", 0o777), but to no avail; that directory seems locked away from me, so I think this is a heroku issue.

Any idea how to handle this?

EDIT: Resolved by using the phoenix dep ex_aws to upload to an Amazon S3 bucket.

Mark Karavan
  • 2,654
  • 1
  • 18
  • 38
  • 1
    Try `File.cp_r!` which will throw an error with the reason which you can then read in the logs. (Same for `File.chmod!` if needed.) If you post the detailed logs after making that change, we might be able to help more. You can also just do `IO.inspect(File.cp_r(...))` to log the return value of that function. – Dogbert Apr 23 '17 at 05:22
  • 1
    @Dogbert `File.cp_r!` shows nothing, `IO.inspect(File.cp_r(...))` shows `{:ok, ["priv/static/images/foo.jpg"]}`, still nothing there. – Mark Karavan Apr 23 '17 at 06:33
  • 1
    Can you confirm this returns nothing: `heroku run find . | grep 'priv/static/images/foo.jpg'`? – Dogbert Apr 23 '17 at 06:47
  • @Dogbert confirmed. As Navin Peiris mentioned below it shows a different instance altogether. My instance also wasn't displaying the file, so if the file WAS being stored in another instance I wouldn't have seen it....moot point since I am going with S3 now anyway. – Mark Karavan Apr 24 '17 at 04:02

1 Answers1

3

The file system on heroku is ephemeral, and you won't have access to any files that you save on it across deploys or when you start new instances.

Also, when you run heroku run, you're not connecting up to that same instance that's currently running your app, instead what it'll do is to launch a new instance so those uploaded files would not exist there.

A better approach is to save the uploaded files to S3 or similar where you can still access it across deploys.

Navin Peiris
  • 2,526
  • 2
  • 24
  • 25
  • The fact that `heroku run` just straight up launches another instance is really crucial. I didn't even notice this and wasted tons of time wondering why Phoenix didn't report any error but the file just didn't show up in my `heroku run bash`... – xji Aug 20 '17 at 00:17