How to upload a image with REST API

Posted by aventofilip on 19-Feb-2018 08:28

Hi, we are currently developing an application on top of Rollbase REST API (see my other thread as well), and is now in need to upload files Rollbase. We are trying with the setBinaryData endpoint, but it seems like it has never been used nor tested with the current documentation alas.

Do you have any specific samples on how to upload a document that is >2MB with the REST API. My field is of the type "File Upload".

Best regards

All Replies

Posted by Srinivas Panyala on 19-Feb-2018 11:29

Hi,

Here is sample code. You have to create a record first then invoke this setBinaryData REST API method.

import java.io.File;
import java.io.FileInputStream;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;

import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;

public class TestSetBinaryData {

      public static void main(String[] args) {

            // Apache HTTP client 3.1
            PostMethod post = new PostMethod();
            HttpClient httpclient = new HttpClient();
            String postResponse = null;

            try {

                
                  post = new PostMethod(
                              "www.rollbase.com/.../setBinaryData

                  // Multi-part upload
                  Part[] p1 = new Part[6];
                  p1[0] = new StringPart("id", "97062227"); // record id
                  p1[1] = new StringPart("objName", "ObjectA"); // object integration name
                  p1[2] = new StringPart("fieldName", "TestFileUpload"); // field integration name
                  p1[3] = new StringPart("contentType", "application/pdf"); // file content type
                  p1[4] = new StringPart("fileName", "Filename.pdf"); // file name

                  File f = new File("C:\\BinaryFileTest\\FileName.pdf"); // actual file
                  FileInputStream fileInputStream = null;
                  byte[] bFile = new byte[(int) f.length()];
                  try {
                        fileInputStream = new FileInputStream(f);
                        fileInputStream.read(bFile);
                        fileInputStream.close();
                  } catch (Exception e) {
                        e.printStackTrace();
                  }
                  String encodeBase64Str = Base64.encodeBase64String(bFile); // Convert to Base64 encoded format
                  System.out.println("length is " + encodeBase64Str.length());
                  p1[5] = new StringPart("value", encodeBase64Str);
                  post.setRequestEntity(new MultipartRequestEntity(p1, post.getParams()));
                  httpclient.executeMethod(post);
                  postResponse = post.getResponseBodyAsString();
                  System.out.println("Response is" + postResponse);

            } catch (Exception e) {
                  e.printStackTrace();
            } finally {

                  post.releaseConnection();
            }

      }

}

Posted by Srinivas Panyala on 19-Feb-2018 11:36

In above reply, syntax highlighters modified a few things. Please check below example.

import java.io.File;

import java.io.FileInputStream;

import org.apache.commons.codec.binary.Base64;

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.methods.PostMethod;

import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;

import org.apache.commons.httpclient.methods.multipart.Part;

import org.apache.commons.httpclient.methods.multipart.StringPart;

public class TestSetBinaryData {

     public static void main(String[] args) {

           // Apache HTTP client 3.1

           PostMethod post = new PostMethod();

           HttpClient httpclient = new HttpClient();

           String postResponse = null;

           try {

                 post = new PostMethod(

                             "www.rollbase.com/.../setBinaryData

                 // Multi-part upload

                 Part[] p1 = new Part[6];

                 p1[0] = new StringPart("id", "97062227"); // record id

                 p1[1] = new StringPart("objName", "ObjectA"); // object integration name

                 p1[2] = new StringPart("fieldName", "TestFileUpload"); // field integration name

                 p1[3] = new StringPart("contentType", "application/pdf"); // file content type

                 p1[4] = new StringPart("fileName", "FileName.pdf"); // file name

                 File f = new File("C:\\BinaryFileTest\\FileName.pdf"); // actual file

                 FileInputStream fileInputStream = null;

                 byte[] bFile = new byte[(int) f.length()];

                 try {

                       fileInputStream = new FileInputStream(f);

                       fileInputStream.read(bFile);

                       fileInputStream.close();

                 } catch (Exception e) {

                       e.printStackTrace();

                 }

                 String encodeBase64Str = Base64.encodeBase64String(bFile); // Convert to Base64 encoded format

                 System.out.println("length is " + encodeBase64Str.length());

                 p1[5] = new StringPart("value", encodeBase64Str);

                 post.setRequestEntity(new MultipartRequestEntity(p1, post.getParams()));

                 httpclient.executeMethod(post);

                 postResponse = post.getResponseBodyAsString();

                 System.out.println("Response is" + postResponse);

           } catch (Exception e) {

                 e.printStackTrace();

           } finally {

                 post.releaseConnection();

           }

     }

}

Thanks

Srinivas

Posted by Srinivas Panyala on 19-Feb-2018 11:41

Attached sample file [View:/cfs-file/__key/communityserver-discussions-components-files/25/TestSetBinaryData.java:320:240]

Posted by aventofilip on 20-Feb-2018 00:34

So what you are saying, that everywhere in the documentation it says "URL Parameter", is actually form-fields?

Posted by marian.edu on 20-Feb-2018 01:38

Only when method is POST/PUT… only that funny enough for setBinaryData both POST and GET(???) methods are accepted, or at least this is what the doc say :)


As for how the data should be formatted it’s all a matter of trial and error, all one can find about it is that “Fields values must be formatted the same way as you would for a CVS import” as for how you should expect the data to be formatted with json/xml output that’s another story :(

What bugs me is, you said you’re building a front-end ui (js, so web or maybe nativescript?) for rollbase… isn’t that the main use case for rollbase, to easily design web apps with no (less) coding? If you’re just looking for some back-end micro-services I don’t think Rollbase is the best option here. 

Marian Edu

Acorn IT 
+40 740 036 212

Posted by aventofilip on 20-Feb-2018 01:51

We are building a small application to support a niche on top of a heavy and complex Rollbase integration developed through years. That is, we need the data and to interact with it. That you think it's not the best option does really not matter here, as it is the only option for what we are trying to solve ;)

However, the documentation should be overhauled if what is discussed here is true, as it lacking and wrong at best. The documentation for setBinaryData don't even mention "objName" as one of it's parameters. Also check my other post community.progress.com/.../37215 where I am addressing the lack of consistency in the endpoints.

Posted by aventofilip on 20-Feb-2018 02:08

All API documentation is both lacking and wrong, and should be updated. setBinaryData documentation does not even mention objName (could figure out that myself though), and we have seen several examples of this. Just look at my other post community.progress.com/.../115253

About the use case, we are developing a niche frontend on top of a heavy and complex Rollbase application. We need to consume and interact with the data, and put everything in a custom designed frontend, so this is actually our only option to this, as far as we know.

Posted by mpiscoso@gmail.com on 20-Feb-2018 02:19

[mention:c18d103734ab4692b34af92c057b1d2c:e9ed411860ed4f2ba0265705b8793d05] Have you tried limiting the tabs/menus of a user's role and just have them login instead of having to "recreate the wheel" so to speak? I assume you're just creating this front-end for a select group of people anyway so why not just assign their users a special "role" instead?

Have you also tried looking into utilizing portals? The output isn't that great but at least you have access to the basics of the platform instead of having nothing and redoing everything using APIs.

I have also had a lot of trouble with the API personally and had to do trial and error most of the time and understand your pain.

You can also use jquery, jquery ui, kendo, and standard HTML and CSS to improve the UI of the app if it needs to be customized in any way.

Hope this helps.

Posted by aventofilip on 20-Feb-2018 02:32

None of those are viable options for our client. We have explored all the other solutions you are mentioning and concluded this is the way to go. The API documentation looks ok if you are just doing some shallow research, but once you try to use it you have weeks of sleepless nights ahead...

Posted by mpiscoso@gmail.com on 20-Feb-2018 02:43

[mention:c18d103734ab4692b34af92c057b1d2c:e9ed411860ed4f2ba0265705b8793d05] I wholeheartedly understand what you're going through being on the same receiving end as well.

Just wondering though why this is the only solution? Does your client require a different URL from where their tenant is installed in? Is their expected UI too far from what the platform offers?

Don't want to overstep but it may be worth looking at again.

I've done various projects before that did not require me to redo the whole front-end using APIs (nor do I want to due to the issues you've been experiencing).

For me, the biggest reason as to why I would not want to redo the UI is because of the capacity that Roles can play. You can easily show/hide tabs, menus, actions, etc. without having to do much. The condition formulas for each of the components within the platform can also be utilized if you're working inside of it as opposed to creating your own.

Hope we can continue this discussion in detail as I am intrigued by your problem (unfortunately it's a problem).

You may contact me at mpiscoso@gmail.com if you want to continue this discussion offline.

Thank you very much,

Piscoso, Martin

Posted by aventofilip on 20-Feb-2018 02:50

This is the only solution because the users should not be let into the Rollbase application, and we are integrating into another portal. The URL are different and the design totally different. We are also way past the point of no return, so now it is really not an option. The end user should not be able to tell that Rollbase is the back end solution here as they are not part of the company that we are developing this for, but needs to input data to a small portion of the Rollbase application.

Posted by mpiscoso@gmail.com on 20-Feb-2018 02:56

That's unfortunate. You really have to work with the API on this one then.

I would have seen that portals would have been the way to go from your description.

Then most likely wrapped within an iframe or frameset or android/ios wrapper.

Anyway, since you can't go back now I wish you and your team luck.

You have my email so if you have any questions that you think I can help you with just shoot a message over.

Piscoso, Martin

Posted by aventofilip on 16-Mar-2018 02:23

Inside Rollbase I have a max file upload of 5120KB,  but when uploading from the REST API using setBinaryData it seems  like the max size is around 1MB. The response when uploading larger files is:

<resp status="fail">

<err>org.apache.http.client.ClientProtocolException</err>

</resp>

and in the rest log it responds with

[2018-03-16 08:09:56,947] [SID=44de8e40c7024ff7968671e8ad0d941f@11012] [Comp=rest] [CustId=11012] [IP=192.168.221.5] setDataField id=null

[2018-03-16 08:09:56,949] [SID=44de8e40c7024ff7968671e8ad0d941f@11012] [Comp=rest] [CustId=11012] [IP=192.168.221.5] ===> Error in thread catalina-exec-19 at 03/16/2018 08:09 AM: Error:

com.rb.rest.services.system.RestException: Record with id null not found

at com.rb.rest.logics.controller.RestApiController.setDataField(RestApiController.java:1357)

at com.rb.rest.logics.servlet.ApiServlet.doPost(ApiServlet.java:102)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at com.rb.core.logics.filter.SessionTimestampFilter.doFilter(SessionTimestampFilter.java:56)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at com.rb.util.web.RequestLoggingFilter.doFilter(RequestLoggingFilter.java:37)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)

at org.apache.catalina.valves.StuckThreadDetectionValve.invoke(StuckThreadDetectionValve.java:208)

at org.apache.catalina.valves.CrawlerSessionManagerValve.invoke(CrawlerSessionManagerValve.java:180)

at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)

at org.apache.catalina.authenticator.SingleSignOn.invoke(SingleSignOn.java:240)

at org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:312)

at org.apache.catalina.valves.RemoteAddrValve.invoke(RemoteAddrValve.java:95)

at org.apache.catalina.valves.RequestFilterValve.process(RequestFilterValve.java:312)

at org.apache.catalina.valves.RemoteHostValve.invoke(RemoteHostValve.java:95)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521)

at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096)

at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

at java.lang.Thread.run(Thread.java:745)

even though I have confirmed that the ID is part of the request, and the same request is sent when the using smaller files that goes through ok.

Is there any place to increase the upload size or something?

Posted by aventofilip on 16-Mar-2018 02:56

I actually found it. Had to increase psc.as.msg.maxpostsize to around 50MB (just to overdo it) in catalina.properties :)

This thread is closed