Direct Upload returning HTTP400 "Upload Not Found"

I’ve a strange situation. I’m using Rails 6.1 with Shrine (3.3) + Uppy (latest) to do Ajax direct uploads. I’m using the “Calling from a Controller” approach because I will eventually need extra control, although I’m not applying any constraints at the moment.

On my dev system at least, I’m seeing the image being copied to the store, and I’m seeing the ActiveRecord object being created. However, Uppy is saying Upload failed, and the http response is “Upload Not Found”.

The method responsible within Shrine is the get_multipart_upload() method of upload_endpoint.rb. It’s looking for to see if request.param has a key called “file”. But that param is not present, hence it returns the 400 Upload Not Found.

The request.params object consists of:

{"relativePath"=>"null", "name"=>"IMG_1436.jpg", "type"=>"image/jpeg", "image_asset"=>{"asset"=>{:filename=>"IMG_1436.jpg", :type=>"image/jpeg", :name=>"image_asset[asset]", :tempfile=>#<Tempfile:/var/folders/8z/b8d93q1n7_n16m3t34r0sdy00000gn/T/RackMultipart20201226-52289-5hhekz.jpg (closed)>, :head=>"Content-Disposition: form-data; name=\"image_asset[asset]\"; filename=\"IMG_1436.jpg\"\r\nContent-Type: image/jpeg\r\n"}}}

The controller end point is almost a copy-and-paste of the documentation (I’ve simplified the some of the model names to make it readable):

class Foo::Bar::UploadsController < ApplicationController

  def image_assets

    @bar = Bar.find(params[:bar_id])
    image_asset_params = params.require(:image_asset).permit(:asset)
    @bar.image_assets.create(image_asset_params)
    set_rack_response ImageAssetUploader.upload_response(:cache, request.env)
  end

  private

  def set_rack_response((status, headers, body))
    self.status = status
    self.headers.merge!(headers)
    self.response_body = body
  end

end

I’m therefore a bit unsure why Shrine is not getting the params it requires, given that I’ve not yet strayed far from the docs as I get to grips with Shine and Uppy.

Any advice greatly appreciated.

Note that the usage of upload_endpoint is intended only for uploading files, not for also creating records around it. I don’t know what your frontend setup is exactly, but the file is being sent in the image_asset.asset param, which upload_endpoint won’t find, because as you said it’s looking for file or files param.

You either need an upload endpoint which will receive file or files, and use default Uppy settings for uploading the file there, or use a custom frontend solution if you want to also create database records with it (though it might work with Uppy as well).

In this case it doesn’t seem like you need upload_endpoint here, because you already seem to be attaching the file in the line above. If you need to return the uploaded file data, you can just return image_asset.asset.to_json in the response.

Hi Janko,

Thanks so much for the prompt reply. I must admit it took me a while to fully digest your reply and then I realised that I had misunderstood the underlying concepts at play.

A web search brought me to a blog post of yours called “Better File Uploads with Shrine: Direct Uploads” (I’m too new to insert as a link). And if I may say so I think it did a great job of explaining what the direct upload approach is trying to achieve and how to make the model aware of the upload. And whilst I can now see how the Upload Endpoint documentation does cover this to some degree, I don’t think it’s as clear, and doesn’t have the same level of examples, and so didn’t click, and hence my mistake with putting the upload and model update together.

Anyway, I’m pleased to say that I now have this working ok having taken the model updating out of the custom endpoint, and then passed the stringified json to the hidden input.

One quick follow up question, if I may: should the cache file be removed automatically after it’s successfully saved and stored in the permanent store? Because the cache dir is filling up despite everything seeming to work correctly.

TIA

Thank you for the feedback on the guide. We try to ensure clarity though it’s hard to reset your mind to different beginner mindset during review. :slight_smile:

For files in Cache Storage - absolutely have a clearing strategy in place that is best suited for your application needs. See an example in the Clearing Cache section of our guides. There is also a clearing cache section in the Storage guides.