7

I'm using Grails 2.4.3 and I have a <g:uploadForm> with method set to post, but I'm not getting a MutlipartRequest in my controller action. Instead I'm getting a Servlet3SecurityContextHolderAwareRequestWrapper which has not getFile() method. I've tried casting, I've tried getting the request out of the wrapper with request.request, and I've tried a bunch of other things I've seen suggested to others with a similar problem, but still no dice. I'm sure I'm missing something simple. I tend to do that, but if anyone can point me in the right direction, I'd be very grateful.

Here's my form:

  <g:uploadForm method="POST" action="uploadSupplemental" >
    <div class="modal-header">
      <h3 class="modal-title" id="myModalLabel">Upload Supplemental Data File</h3>
    </div>
    <div class="modal-body">
      <label for="fileInput">Choose file to upload:</label>
      <input type="file" id="fileInput" name="supplementalData" />
    </div>
    <div class="modal-footer">
      <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
      <input type="submit" class="btn btn-primary" />
    </div>
  </g:uploadForm>

And here's my controller action:

  def uploadSupplemental() {
    MultipartRequest multipartRequest =  request as MultipartRequest
    def file = multipartRequest.getFile('supplementalData')
    if (file){
      flash.message = "File found!!"
    } else {
      flash.message = "File NOT found.  :-( "
    }
    redirect action:'list'
  }

And here's the error I get:

URI /app/upload/uploadSupplemental Class groovy.lang.MissingMethodException Message No signature of method: org.springframework.security.web.servletapi.HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper.getFile() is applicable for argument types: (java.lang.String) values: [supplementalData] Possible solutions: getXML(), getPart(java.lang.String), getAt(java.lang.String), getAt(java.lang.String), getLocale(), getJSON()

ABC
  • 4,263
  • 10
  • 45
  • 72
Dave Klein
  • 207
  • 2
  • 10
  • Some more info: The first time I access the request, inside my controller action, the request is of type: org.springframework.security.web.servletapi.HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper. If I call getRequest() on that, I get a org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper. Still a wrapper, so I call getRequest on that and get a org.springframework.security.web.firewall.RequestWrapper, another wrapper. (continued...) – Dave Klein Sep 09 '14 at 14:29
  • One more call to org.springframework.security.web.firewall.RequestWrapper.getRequest gives me a org.apache.catalina.core.ApplicationHttpRequest. So I finally have a request object, but it's not the MultipartRequest that it's supposed to be. Still stumped. – Dave Klein Sep 09 '14 at 14:33
  • What is the value of the `grails.web.disable.multipart` set to in `Config.groovy`? Here is a related [JIRA issue](https://jira.grails.org/browse/GPSPRINGSECURITYCORE-191) and a [duplicate question in SO](http://stackoverflow.com/questions/21764419/grails-upload-file-no-signature-for-method-getfile) reporting the same exception. Also make sure the user is authenticated before the upload action. It is sure that `@Secured` is used in controller. – dmahapatro Sep 12 '14 at 16:16
  • @dmahapatro, That did the trick. Thanks! Can you put this into an answer? – Dave Klein Sep 17 '14 at 14:50
  • Done. Glad that digging was helpful. :) – dmahapatro Sep 17 '14 at 15:22

2 Answers2

2

The following config property has to be set to true in Config.groovy in order to enable multipart requests.

grails.web.disable.multipart=true

Here is a related JIRA issue and a duplicate question in SO reporting the same exception.

Also make sure the user is authenticated (with @Secured) before the upload action.

Community
  • 1
  • 1
dmahapatro
  • 49,365
  • 7
  • 88
  • 117
  • 1
    this solution does not work for me, but i dont have the secured annotaion but i also get HttpServlet3RequestFactory$Servlet3SecurityContextHolderAwareRequestWrapper. An idea how to solve this? Note: The upload works on desktop but not on mobile – Mephiztopheles Dec 09 '14 at 11:52
0

I had exactly the same error in my grails application and came up with the following solution:

The type of the request instance in my app was related to the content-type attribute inside the HTTP post that reaches the server. So, if I had a file input inside a form with enctype attribute set like...

<form enctype="multipart/form-data" action="upload" method="POST">

... I got a MutlipartRequest as expected and could get the uploaded file calling request.getFile().

But if the HTTP post had a content-type of "application/octet-stream" (as when we use Valum's AJAX File-Uploader to upload a single file), than the request is, itself, a binary file and can be converted to an InputStream by calling request.getInputStream().

So, if you're not sure what content-type is being used in your app, I recommend checking it with a browser tool like firebug and trying request.getInputStream() to get the file straight from the request.

See the diference between content-type and enctype

Community
  • 1
  • 1
Cléssio Mendes
  • 996
  • 1
  • 9
  • 25