Question
· Sept 28, 2023

Récupération de fichier d'une api REST et envoie sur un FTP

Bonjour,

Je cherche a créer un flux qui doit appeler une API qui me permet de récupérer le contenu d'un fichier.

pour se faire j'ai créer une classe qui hérite de Ens.BusinessService pour l'appel api

Method OnProcessInput(pInput As %RegisteredObject, Output pOutput As %RegisteredObject) As %Status
{

    Set sc = $$$OK
    set res = ##class(Ens.StringResponse).%New()
    set request = ##class(%Net.HttpRequest).%New()
    set response = ##class(%Net.HttpResponse).%New()
    set request.Https = 1
    set request.Server = ..ServerAddress
    set request.Port = ..Port
    set request.SSLConfiguration = ..SSLConfiguration
    Try {
        set url = ..Path _ "/exportArticles_"_$ZDATE($HOROLOG,8)_".csv"
        set status = request.Get(url)
        $$$TRACE("request.HttpResponse.Data :"_request.HttpResponse.Data)
        set content = ##class(Ens.StreamContainer).%New()
        set stream = ##class(%Stream.GlobalCharacter).%New()
        do stream.Write(request.HttpResponse.Data)
        $$$TRACE("sc : " _ request.HttpResponse.StatusCode)
        $$$TRACE("stream size:"_stream.Size)
        set content.Stream = stream
        $$$TRACE("stream :"_stream.Read(1000))
        set sc = ..SendRequestSync(..TargetConfigNames, content)
    }
    Catch ex {
        set status= ex.AsStatus()
        $$$TRACE("erreur : "_status)
    }

    set result = request.HttpResponse.StatusCode
    if (result '= 200) {
        $$$TRACE("status: "_ result)
    }
    return $$$OK
}

et une de type Ens.BusinessOperation pour l'envoie en ftp

Class SupplyChain.exportArticleHaby Extends Ens.BusinessOperation
{

Property Adapter As EnsLib.FTP.OutboundAdapter;
Parameter ADAPTER = "EnsLib.FTP.OutboundAdapter";
Parameter INVOCATION = "Queue";
Method putFileStream(pRequest As Ens.StreamContainer, Output pResponse As Ens.Response) As %Status
{
    $$$TRACE("pRequest : "_ pRequest)
    Try {
        set fileName = "exportArticles_"_$ZDATE($HOROLOG,8)_".csv"
        set esc = ..Adapter.PutStream(fileName, pRequest.Stream())
    }
    Catch ex {
        $$$TRACE("statusCode: " _ esc)
        Set tSC=ex.AsStatus()
    }
    return $$$OK
}

XData MessageMap
{
<MapItems>
    <MapItem MessageType="Ens.StreamContainer">
        <Method>putFileStream</Method>
    </MapItem>
</MapItems>
}

}

Cependant dans ma production, j'ai l'impression que ma business opération n'est pas appelé, je ne vois pas la trace que j'ai dans ma classe,

Le service est bien lié a l'opération dans ma production, j'ai bien les trace de mon service, je reçoi bien un statut 200 de l'api.

Version du produit: IRIS 2023.2
$ZV: IRIS for Windows (x86-64) 2022.1 (Build 209U) Tue May 31 2022 12:16:40 EDT
Discussion (6)2
Connectez-vous ou inscrivez-vous pour continuer

Bonjour @Jean-Charles Cano ,

Pour le passage d'un stream à un autre, j'éviterai d'utiliser la fonction Write si vous ne bouclez pas sur le stream d'entrée.

En effet, la fonction Write fonctionne par chunks, donc si vous n'avez pas lu tout le stream d'entrée, vous risquez de ne pas avoir tout écrit dans le stream de sortie.

Comme vous utilisez la classe Ens.StreamContainer, vous pouvez utiliser le constructeur qui prend en paramètre un stream d'entrée et qui copie le contenu complet du stream d'entrée dans la variable de Stream du StreamContainer.

Method OnProcessInput(pInput As %RegisteredObject, Output pOutput As %RegisteredObject) As %Status
{

    Set sc = $$$OK
    set res = ##class(Ens.StringResponse).%New()
    set request = ##class(%Net.HttpRequest).%New()
    set response = ##class(%Net.HttpResponse).%New()
    set request.Https = 1
    set request.Server = ..ServerAddress
    set request.Port = ..Port
    set request.SSLConfiguration = ..SSLConfiguration
    Try {
        set url = ..Path _ "/exportArticles_"_$ZDATE($HOROLOG,8)_".csv"
        set status = request.Get(url)
        $$$TRACE("request.HttpResponse.Data :"_request.HttpResponse.Data)

        #; Commented code to show the difference between the two methods
        #; set content = ##class(Ens.StreamContainer).%New()
        #; set stream = ##class(%Stream.GlobalCharacter).%New()
        #; do stream.Write(request.HttpResponse.Data)

        #; Recommended method
        set content = ##class(Ens.StreamContainer).%New(request.HttpResponse.Data)

        #; Other methods by looping on the stream
        #; set content = ##class(Ens.StreamContainer).%New()
        #; set stream = ##class(%Stream.GlobalCharacter).%New()
        #; while 'request.HttpResponse.Data.AtEnd {
        #;     set stream.Write(request.HttpResponse.Data.Read())
        #; }
        #; set content.Stream = stream

        $$$TRACE("sc : " _ request.HttpResponse.StatusCode)
        #; Old code
        #; $$$TRACE("stream size:"_stream.Size)
        #; set content.Stream = stream
        #; $$$TRACE("stream :"_stream.Read(1000))

        #; New code
        $$$TRACE("content.Stream.Size :"_content.Stream.Size)
        $$$TRACE("content.Stream :"_content.Stream.Read(1000))

        set sc = ..SendRequestSync(..TargetConfigNames, content)
    }
    Catch ex {
        set status= ex.AsStatus()
        $$$TRACE("erreur : "_status)
    }

    set result = request.HttpResponse.StatusCode
    if (result '= 200) {
        $$$TRACE("status: "_ result)
    }
    return $$$OK
}

Ensuite pour la partie écriture avec l'adapter FTP,vous pouvez utiliser la methode PutStream de l'adapter FTP.

Class SupplyChain.exportArticleHaby Extends Ens.BusinessOperation
{

Property Adapter As EnsLib.FTP.OutboundAdapter;
Parameter ADAPTER = "EnsLib.FTP.OutboundAdapter";
Parameter INVOCATION = "Queue";
Method putFileStream(pRequest As Ens.StreamContainer, Output pResponse As Ens.Response) As %Status
{
    $$$TRACE("pRequest : "_ pRequest)
    Try {
        set fileName = "exportArticles_"_$ZDATE($HOROLOG,8)_".csv"
        set esc = ..Adapter.PutStream(fileName, pRequest.Stream)
    }
    Catch ex {
        $$$TRACE("statusCode: " _ esc)
        Set tSC=ex.AsStatus()
    }
    return $$$OK
}

XData MessageMap
{
<MapItems>
    <MapItem MessageType="Ens.StreamContainer">
        <Method>putFileStream</Method>
    </MapItem>
</MapItems>
}

}