Upload file to REST (Data Object WebSpeed service) - Forum - OpenEdge Development - Progress Community

Upload file to REST (Data Object WebSpeed service)

 Forum

Upload file to REST (Data Object WebSpeed service)

This question is answered

We are using OE 11.7.2 on Windows 7 and Server 2012R2 (both 64 bit) and have a REST API using a Data Object WS service for a Kendo UI Builder app.

Our app needs to be able to upload a file for processing and I'm struggling to figure out how to implement this on the backend.  Since I'm not sure what the signature of the POST method should be, I've been trying different things and nothing works.  The latest trial is the following:

   @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
   @progress.service.resourceMapping(type="REST", operation="create", URI="", alias="", mediaType="application/octet-stream").
   METHOD PUBLIC VOID UploadAcctCat(INPUT mpEntity AS OpenEdge.Net.MultipartEntity):
      
      MESSAGE "Received " mpEntity:Size " parts".

/* Save contents to a temp file for processing... */
END METHOD. /* UploadAcctCat */

When my KUIB app tries calling this URI, I get the following in the oepas1.agent.log:

[18/01/25@09:31:41.622-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr [OE.W.DO.DOH.UI ERROR] Exception raised for POST localhost:8810/.../UploadProfitAcctCat; Entity=UploadProfitAcctCat_4126; Operation=OpenEdge.Web.DataObject.MappedOperation_3508: POST svc:UI v1.0.0 uri:UploadProfitAcctCat: type:Class ; name:Progress.Lang.Object, type-of:Progress.Lang.Object, fn:, numargs:3, num-schemas:0, name:
[18/01/25@09:31:41.622-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Error(s) raised:
[18/01/25@09:31:41.622-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Unsupported object type: OpenEdge.Net.MultipartEntity (0)
[18/01/25@09:31:41.653-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr [OE.W.DO.DOH.UI ERROR] Error writing exception
[18/01/25@09:31:41.653-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Error(s) raised:
[18/01/25@09:31:41.653-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Unsupported object type: Progress.Lang.AppError (0)

Any thoughts on how to implement a file upload backend REST service?

Louis Winter

Verified Answer
  • Louis,
     
    From the docs you linked, it looks like the operations (error/success) expect the same JSON responses
    Event Data
    e.files Array
     
    Lists the files that were uploaded or removed.
     
    Each file has:
     
        name
        extension - The file extension including the leading dot. For example, .jpg, .png, an so on.
        size - The file size in bytes. If not available, the value is null.
        uid - The unique identifier of the file or batch of files.
     
    e.operation String
     
    The upload or remove operation.
    e.XMLHttpRequest Object
     
    Represents either the original XHR that is used for the operation or a stub that contains:
     
        responseText
        status
        statusText
     
    Before you access any other fields, verify that this is an actual XHR.
     
    The docs aren’t clear on how you signal an error vs success (I’d think a status code). You can do this with a custom map file too.
     
    You can build the whole JSON yourself (easiest for now, I think) by tweaking your method’s signature to be
      METHOD PUBLIC INTEGER UploadFile(INPUT mpEntity AS OpenEdge.Net.MultipartEntity,
                                       OUTPUT pResponse AS JsonObject):
     
    And the mapping entry to
    {
      "services": {
        "UI": {
          "version": "1.0.0",
          "operations": {
            "/UploadFile": {
              "POST": {
                "contentType": "application/json",
                "entity": {
                  "name": "UploadFileClass",
                  "function": "UploadFile",
                  "arg": [
                    {
                      "ablName": "",
                      "ablType": "INTEGER",
                      "ioMode": "RETURN",
                      "msgElem": {"type": "StatusCode", "name": null}
                    },
                    {
                      "ablName": "mpEntity",
                      "ablType": "CLASS OpenEdge.Net.MultipartEntity",
                      "ioMode": "INPUT",
                      "msgElem": {"type": "BODY", "name": null}
                    },
                    {
                      "ablName": "pData",
                      "ablType": "CLASS Progress.Json.ObjectModel.JsonObject",
                      "ioMode": "OUTPUT",
                      "msgElem": {"type": "BODY", "name": null}
                    }
                  ]
                }
              }
            }
          },
          "schemas": null
        }
      }
    }
     
     
     
     
All Replies
  • Hey Louis,

    Currently we don't parse/separate the multipart parts for you (you should log a bug for this).

    What you can currently do is to add  manual mapping so that the request body is passed into the method as a multipart entity, and then you'll have to split the multipart entity part.

    If you can post the <service-name>.gen file in the WEB-INF/openedge folder of the webapp (its default location), then I can help you with the tweaks you'll need.

  • Peter,

    I wasn't sure if I was going to get a reply on this issue so I just opened up a case this afternoon.  If I upload my gen file to the case can you access it?

    Louis

  • Yes, that’ll work just fine.
  • Excellent, I just uploaded a .zip file with the .gen file along with my EventHandler class (in case you need to see it).  The case is 00432333.  Thanks!

  • Thanks Peter, the .map file you provided works great once I got my environment updated.

    Now, how do you recommend returning errors back to KUIB?  The upload widget has an error event (docs.telerik.com/.../upload and it looks like the only information I can return is responseText, status, and statusText.  With the ABL method only having a single input value of OpenEdge.Net.MultipartEntity, I'm not sure how to return error information (determined by my validation and processing logic).

    Louis Winter

  • Louis,
     
    From the docs you linked, it looks like the operations (error/success) expect the same JSON responses
    Event Data
    e.files Array
     
    Lists the files that were uploaded or removed.
     
    Each file has:
     
        name
        extension - The file extension including the leading dot. For example, .jpg, .png, an so on.
        size - The file size in bytes. If not available, the value is null.
        uid - The unique identifier of the file or batch of files.
     
    e.operation String
     
    The upload or remove operation.
    e.XMLHttpRequest Object
     
    Represents either the original XHR that is used for the operation or a stub that contains:
     
        responseText
        status
        statusText
     
    Before you access any other fields, verify that this is an actual XHR.
     
    The docs aren’t clear on how you signal an error vs success (I’d think a status code). You can do this with a custom map file too.
     
    You can build the whole JSON yourself (easiest for now, I think) by tweaking your method’s signature to be
      METHOD PUBLIC INTEGER UploadFile(INPUT mpEntity AS OpenEdge.Net.MultipartEntity,
                                       OUTPUT pResponse AS JsonObject):
     
    And the mapping entry to
    {
      "services": {
        "UI": {
          "version": "1.0.0",
          "operations": {
            "/UploadFile": {
              "POST": {
                "contentType": "application/json",
                "entity": {
                  "name": "UploadFileClass",
                  "function": "UploadFile",
                  "arg": [
                    {
                      "ablName": "",
                      "ablType": "INTEGER",
                      "ioMode": "RETURN",
                      "msgElem": {"type": "StatusCode", "name": null}
                    },
                    {
                      "ablName": "mpEntity",
                      "ablType": "CLASS OpenEdge.Net.MultipartEntity",
                      "ioMode": "INPUT",
                      "msgElem": {"type": "BODY", "name": null}
                    },
                    {
                      "ablName": "pData",
                      "ablType": "CLASS Progress.Json.ObjectModel.JsonObject",
                      "ioMode": "OUTPUT",
                      "msgElem": {"type": "BODY", "name": null}
                    }
                  ]
                }
              }
            }
          },
          "schemas": null
        }
      }
    }
     
     
     
     
  • Thanks Peter, the changes to the map file are working perfectly.

    Louis

  • Peter,

    Are there any settings or some way to speed up the MultipartEntity REST call?  My method works in that I can save the file being uploaded, but I noticed a large pause in the interface.  The following log file entries show what's happening.  Check out the time between the MPARTENT log entry and the next entry which appears to be when my upload method is actually called (1 minute and 47 seconds).

    [18/02/13@09:00:07.959-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.InternalWebRouter DEBUG] Request for path "/JTS/web/pdo/UI/UploadProfitAcctCat" using template "/pdo/" and handler "OpenEdge.Web.DataObject.DataObjectHandler"

    [18/02/13@09:00:07.967-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.InternalWebRouter DEBUG] Debug mode: ON

    [18/02/13@09:00:07.983-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.InternalWebRouter DEBUG] Handler instance OpenEdge.Web.DataObject.DataObjectHandler_4209 used for handler OpenEdge.Web.DataObject.DataObjectHandler

    [18/02/13@09:00:08.133-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     INFO: Current session client type MULTI-SESSION-AGENT does not support named logs

    [18/02/13@09:00:08.199-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DataObjectHandler DEBUG] Using mapped operation for POST service path UploadProfitAcctCat: OpenEdge.Web.DataObject.MappedOperation_3688: POST svc:UI v1.0.0 uri:UploadProfitAcctCat: type:Class ; name:Progress.Lang.Object, type-of:Progress.Lang.Object, fn:, numargs:2, num-schemas:0, name:

    [18/02/13@09:00:08.352-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     INFO: Current session client type MULTI-SESSION-AGENT does not support named logs

    [18/02/13@09:00:08.357-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DataObjectHandler INFO] Service UI logging performed by OpenEdge.Web.DataObject.DataObjectHandler.UI at DEBUG

    [18/02/13@09:00:08.365-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] "Accept" value: */*; q=0.5, application/json

    [18/02/13@09:00:08.367-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Operation ContentType: application/json

    [18/02/13@09:00:08.426-0600] P-021284 T-016484 1 AS-4 MPARTENT       DEBUG FILE=C:\OpenEdge\WRK\oepas1\temp\mpe-4354.txt

    [18/02/13@09:01:55.422-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Business entity UploadProfitAcctCat (type-of Progress.Lang.Object) invoked by OpenEdge.Web.DataObject.DataObjectHandler_4209 as target type Class

    [18/02/13@09:01:55.481-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Using business entity 4409 of type UploadProfitAcctCat

    [18/02/13@09:01:55.484-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Using entity UploadProfitAcctCat_4409 for operation OpenEdge.Web.DataObject.MappedOperation_3688: POST svc:UI v1.0.0 uri:UploadProfitAcctCat: type:Class ; name:Progress.Lang.Object, type-of:Progress.Lang.Object, fn:, numargs:2, num-schemas:0, name:

    [18/02/13@09:01:55.591-0600] P-021284 T-016484 1 AS-4 -- (Procedure: 'Logit JTSConfig' Line:451) [5] UploadProfitAcctCat:UploadAcctCat() Received 1 parts

    [18/02/13@09:01:57.647-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Cached entity "UploadProfitAcctCat" removed for service "UI" 1.0.0

    Louis

  • Louis,

    Would you mind contacting tech support? And could you send them the request (including the multipart body)?

  • Will do.

    Louis