Sending File and JSON from Angular to Restlet

412 views Asked by At

I have a form that includes an object bound to the html with ng-bind. The same form includes a fileupload widget: <input type="file" id="uploadedFile" name="uploadedFile">.

I'm submitting this to a Java Restlet. I am able to get the File in the restlet but the json that should represent my object is null. Is there a way to solve this?

Here's my code. On the angular side:

function saveMap2(map, fileToUpload) {

    var formData = new FormData();
    formData.append("map", map);
    formData.append("file", fileToUpload);

    var deferred = $q.defer();
    $http.post(REST_SAVE_MAP_URI, formData, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined}
    })
    .then(
      function (response) {
        deferred.resolve(response.data);
    },
    function(errResponse) {
        console.error('Error while saveMap');
        deferred.reject(errResponse);
    });
    return deferred.promise;
}

On the Restlet side:

@Post
public Representation doPost(Representation entity) {
    try {
        System.out.println("Media type? " + entity.getMediaType());
        DiskFileItemFactory factory = new DiskFileItemFactory();
        factory.setSizeThreshold(1000240);
        RestletFileUpload upload = new RestletFileUpload(factory);
        FileItemIterator fileIterator = upload.getItemIterator(entity);

        while (fileIterator.hasNext()) {
               FileItemStream fi = fileIterator.next();
               String fieldName = fi.getFieldName();
               String contentType = fi.getContentType();
               System.out.println("FIELD = " + fieldName + ": " + fi);
               if (!fi.isFormField()) {
                  String fileName = fi.getName();
                  System.out.println("name? " + fileName);

                  InputStream is = new BufferedInputStream(fi.openStream());
                  BufferedOutputStream output = null;

                  try {
                      output = new BufferedOutputStream(new FileOutputStream("/path/" + fileName, false));
                      int data = -1;
                      while ((data = is.read()) != -1) {
                          output.write(data);
                      }
                  } finally {
                      is.close();
                      output.close();
                  }
               } 
        }
  }

The result is that the image I'm uploading is saved correctly, but I don't know how to get the map json.

Here's some output:

Media type? multipart/form-data; boundary=----WebKitFormBoundary9GSUTgCJ4NbnnoT8
FIELD = map:  org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl$FileItemStreamImpl@54d1ffff
FIELD = file: org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl$FileItemStreamImpl@5a160b15
name? IMG_5327.JPG

When I'm printing the entity it seems like the request is fine:

'------WebKitFormBoundarysmqftmsA0EFDlceo
Content-Disposition: form-data; name="map"

[object Object]
------WebKitFormBoundarysmqftmsA0EFDlceo
Content-Disposition: form-data; name="file"; filename="IMG_5327.JPG"
Content-Type: image/jpeg

Any idea how to solve this? How can I get both the json and the file from the same request?

1

There are 1 answers

0
Eddy On

I solved it by sending the json object in the query, and getting it in the restlet by using the HttpServletRequest and pulling the relevant parameter from it.

Looking at the code in the question this is the modification on the angular side:

$http.post(REST_SAVE_MAP_URI + "?map=" + JSON.stringify(map), formData, {...

and in the restlet:

org.restlet.Request restletRequest = getRequest();
HttpServletRequest servletRequest = ServletUtils.getRequest(restletRequest);
String mapJson = servletRequest.getParameter("map"));
Gson gson = new Gson();
Map map = gson.fromJson(servletRequest.getParameter("map"), Map.class);

Everything else on both the restlet and angular side is exactly the same.