Logo

    Home

    Documentation

    Use Cases

    Training

    Applications

    Release Notes

    Support for handling the upload of a file and sending it to the back-end

    Support for handling the upload of a file and sending it to the back-end

    icon
    This Use Case how to manage the Backend Logic to support a file uploaded with a File Input field in the UI of a Build. One Application
    • 1. Summary
    • 2. Step by Step Guide
    • 2.1 Registering a new handler
    • 2.2 Passing Parameters
    • 2.3 Supported events
    • 2.4 Additional parameters
    • Sample web handler
    • SwatInput Attributes for UPLOAD (Subtype)
    • 3. Documentation

    1. Summary

    Support is needed for handling the upload of files and efficiently sending them to the back-end. This involves registering a new web-handler, passing necessary parameters, and managing various upload events and additional parameters to ensure smooth operation. The document also includes sample code for setting up the web-handler and provides alternatives for using the SwatUpload control.

    2. Step by Step Guide

    2.1 Registering a new handler

    In SWAT, a new web-handler must be registered in openedge.properties, similar to AppDataWebHandler, under: [app.ROOT.WEB]

    [app.restbasic.WEB]

    A new entry must be added: handlerXX=path.to.class: /{URL}/{path-param-1}/{path-param-2}

    2.2 Passing Parameters

    //PATH PARAMS: 
    poRequest:GetPathParameter ("path-param-1":U)
    
    //QUERY PARAMS:
    DEFINE VARIABLE oQueryString AS CharacterDictionary NO-UNDO.
    
    ListHelper:AlternatingListToDictionary(STRING(poRequest:GetContextValue("QUERY_STRING")), "&", "=").
    
    WEB-CONTEXT:URL-DECODE(oQueryString:GetValue("Value")).

    In the SwatInput or DynFillin, the upload URL must be specified:

    • in the uploadURL attribute
    • by calling .setURL() on the upload control from the EventUploadFileAdd function
    • uploadURL must include the /web prefix.

    2.3 Supported events

    Events
    Description
    EventUploadComplete
    Fires when all files from the list have been uploaded to the server
    EventUploadFileAdd
    Fires when the user adds a file to the upload queue
    EventUploadBeforeFileAdd
    Fires when the user adds a file to the upload queue
    EventUploadFail
    Fires when the file upload has failed
    EventUploadBeforeClear
    Fires before the clear event is triggered; can prevent clear event if the function returns the following: return { preventAction: true };
    EventUploadClear
    Fires on clear files; only if not prevented
    EventUploadBeforeFileRemove
    Fires before a single file is removed from the list; can prevent remove event if the function returns the following: return { preventAction: true };
    EventUploadFileRemove
    Fires when a single file is removed from the list; only if remove is not prevented

    2.4 Additional parameters

    Parameter
    Description
    setAutoRemove
    enables the mode in which files are immediately removed from the item after downloading has been completed
    setAutoStart
    Enables the mode in which files are immediately loaded after selecting
    uploadTooltip
    Attribute where you can specify the tooltip values for the different buttons; Accepts a json string (default: {}), where you can sppecify the different tooltips: browse,upload, cancel, clear

    JSON example:

    {"browse": "new label", "clean": "new clean label"}

    Tooltip labels are also translatable in the common files. Place a custom translation under:

    upload.tooltip.<name-of-key>

    where name-of-key is one of the above 4.

    "upload": {
      "tooltip": {
        "browse": "Search",
        "clear": "Remove"
      }
    },

    Sample web handler

    FileUploadWebHandler.cls is a working example in SWAT.

    icon
    ALTERNATIVELY, here is a working example from OpenEdge on working with webHandlers:

    https://community.progress.com/s/article/How-to-load-a-binary-file-with-webhandlers

    Alternatively, the SwatUpload control can be used, if the desired outcome is just uploading files to the backend and assigning the value in a form field.

    For the form field, a swat input(left) or dynfillin(right) can be used. Either must be of subtype UPLOAD:

    image

    Limitations: events are bound on the form, for all children of type 'upload'; only one upload control should be used in a form.

    SwatInput Attributes for UPLOAD (Subtype)

    • multipleFileSelection (default: true) - This attribute defines whether the user can select a single file (false) or multiple files (true) for uploading.

    3. Documentation

    To find more information, you can check the following documentation.

    FieldField

    Back to Use CasesUse Cases

    Back to Build.One Help-CenterBuild.One Help-Center Home

    Logo
    USING Progress.Lang.*.
    USING Progress.Json.ObjectModel.JsonObject FROM PROPATH.
    USING OpenEdge.Web.WebResponse FROM PROPATH.
    USING OpenEdge.Web.IWebRequest FROM PROPATH.
    USING OpenEdge.Net.HTTP.IHttpResponse FROM PROPATH.
    USING OpenEdge.Net.HTTP.StatusCodeEnum FROM PROPATH.
    USING Consultingwerk.Framework.Collections.CharacterDictionary FROM PROPATH.
    USING Consultingwerk.Util.ListHelper FROM PROPATH.
    USING Consultingwerk.OERA.ServiceInterface FROM PROPATH.
    USING Consultingwerk.Util.GarbageCollectorHelper FROM PROPATH.
    USING Consultingwerk.Exceptions.Exception FROM PROPATH.
    USING Akioma.Swat.Util.FileHelper FROM PROPATH.
    
    CLASS Akioma.Swat.OERA.WebHandler.Test
      INHERITS Consultingwerk.OERA.JsdoGenericService.WebHandler.SmartWebHandler:
    
        METHOD OVERRIDE PROTECTED INTEGER HandlePost(poRequest AS IWebRequest):
          DEFINE VARIABLE cFileName    AS CHARACTER           NO-UNDO.
          DEFINE VARIABLE cFullPath    AS CHARACTER           NO-UNDO.
          DEFINE VARIABLE cPathParam   AS CHARACTER           NO-UNDO.
          DEFINE VARIABLE cValue       AS CHARACTER           NO-UNDO.
          DEFINE VARIABLE pData        AS MEMPTR              NO-UNDO.
    
          DEFINE VARIABLE oQueryString AS CharacterDictionary NO-UNDO.
          DEFINE VARIABLE oResponse    AS IHttpResponse       NO-UNDO.
    
          ASSIGN
            oResponse             = NEW WebResponse()
            oResponse:ContentType = "application/json"
            cPathParam            = poRequest:GetPathParameter ("Test":U).
            oQueryString          = ListHelper:AlternatingListToDictionary(STRING(poRequest:GetContextValue("QUERY_STRING")), "&", "=")
            .
    
          DO ON ERROR UNDO, THROW:
            ServiceInterface:Activate().
    
            ASSIGN
                cValue = WEB-CONTEXT:URL-DECODE(oQueryString:GetValue("Value")) 
                WHEN oQueryString:ContainsKey("Value")
                .
    
    MESSAGE 'cPathParam is ' cPathParam.
    MESSAGE 'cValue     is ' cPathParam.
    
            cFullPath = SESSION:TEMP-DIR + 'test.txt'.
    
            pData = WEB-CONTEXT:GET-BINARY-DATA("file").
            COPY-LOB FROM pData TO FILE FileHelper:GetFileSystemPath(cFullPath).
    
            oResponse:StatusCode = INTEGER (StatusCodeEnum:OK).
            THIS-OBJECT:WriteJsonResponse(oResponse, cFileName, TRUE, "").
            RETURN 0.
          END.
    
          CATCH oError AS Progress.Lang.Error:
            oResponse:StatusCode = INTEGER(StatusCodeEnum:BadRequest).
            THIS-OBJECT:WriteJsonErrorResponse(oResponse, cFileName, oError).
            RETURN 500.
          END CATCH.
    
          FINALLY:
              SET-SIZE(pData) = 0.
    
              ServiceInterface:Deactivate().
          END FINALLY.
      END METHOD.
    
      METHOD PRIVATE VOID WriteJsonErrorResponse(
        INPUT poResponse    AS IHttpResponse,
        INPUT pcFileName    AS CHARACTER,
        INPUT poError       AS Progress.Lang.Error
        ):
    
        DEFINE VARIABLE cMessage AS CHARACTER NO-UNDO.
        DEFINE VARIABLE iIdx     AS INTEGER   NO-UNDO. 
    
        cMessage = "".
    
        DO iIdx = 1 TO poError:NumMessages:
            cMessage = cMessage
                + (IF cMessage <> "" THEN "~n" ELSE "")
                + poError:GetMessage(iIdx)
                .            
        END.
        
        IF TYPE-OF(poError, Progress.Lang.AppError) AND CAST(poError, Progress.Lang.AppError):ReturnValue > "" THEN
            cMessage = cMessage
                + (IF cMessage <> "" THEN "~n" ELSE "")
                + CAST(poError, Progress.Lang.AppError):ReturnValue
                .            
    
        THIS-OBJECT:WriteJsonResponse(poResponse, pcFileName, FALSE, cMessage).
      END METHOD.
    
      METHOD PRIVATE VOID WriteJsonResponse(
          INPUT poResponse    AS IHttpResponse,
          INPUT pcFileName    AS CHARACTER,
          INPUT plSuccess     AS LOGICAL,
          INPUT pcMessage     AS CHARACTER
          ):
              
          DEFINE VARIABLE oResponseJson      AS JsonObject NO-UNDO.
          DEFINE VARIABLE oResponseExtraJson AS JsonObject NO-UNDO.
    
          oResponseJson = NEW JsonObject().
          oResponseJson:Add("filename", pcFileName).
          oResponseJson:Add("state", TRUE).
    
          oResponseExtraJson = NEW JsonObject().
          oResponseExtraJson:Add("success", plSuccess).
          oResponseExtraJson:Add("message", pcMessage).
          oResponseJson:Add("extra", oResponseExtraJson).
    
          poResponse:Entity = oResponseJson.
          poResponse:ContentType = "application/json".
    
          THIS-OBJECT:WriteResponse(poResponse).
    
          FINALLY:
              GarbageCollectorHelper:DeleteObject(oResponseExtraJson).
              GarbageCollectorHelper:DeleteObject(oResponseJson).
          END FINALLY.
      END METHOD.
    END CLASS.