Écrit par

Bastide Le Confort Médical
Question Jean-Charles Cano · 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 = $$$OKset res = ##class(Ens.StringResponse).%New()
    set request = ##class(%Net.HttpRequest).%New()
    set response = ##class(%Net.HttpResponse).%New()
    set request.Https = 1set request.Server = ..ServerAddressset request.Port = ..Portset request.SSLConfiguration = ..SSLConfigurationTry {
        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.

Product version: IRIS 2023.2
$ZV: IRIS for Windows (x86-64) 2022.1 (Build 209U) Tue May 31 2022 12:16:40 EDT

Comments

Sylvain Guilbaud · Sept 28, 2023

Bonjour @Jean-Charles.Cano,

Stream n'est pas une méthode mais une propriété ; aussi, tout devrait aller mieux après avoir remplacé cette ligne : 

set esc = ..Adapter.PutStream(fileName, pRequest.Stream())

par celle-ci :

set esc = ..Adapter.PutStream(fileName, pRequest.Stream)
0
Jean-Charles Cano  Sept 29, 2023 to Sylvain Guilbaud

Bonjour Sylvain, 

merci pour ta réponse, cela fonctionne.

0
Jean-Charles Cano  Oct 10, 2023 to Sylvain Guilbaud

update,

en fait cela fonctionne mais dans mon fichier CSV déposé sur le serveur FTP, j'ai comme contenu : 

9@%Stream.GlobalBinary

Et non le contenu des fichiers que je dois récupérer de l'API

0
Guillaume Rongier  Oct 16, 2023 to Jean-Charles Cano

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>
}

}
0
Jean-Charles Cano  Oct 17, 2023 to Guillaume Rongier

Bonjour,

merci pour vos explications, c'est plus clair maintenant et ça fonctionne.

0