Returning a zip file from an eXist-db RestXQ call

57 views Asked by At

I am working on creating a zip file of several XML documents from eXist-db. This method creates the zip file, but does not return it. I tried storing in exist, but the zip file is not the proper format. How do I get the call to return the zip file?

eXist-db version 6.1.0-SNAPSHOT. The latest pull of the JWT branch.

(:~

@param $jwt The JWT authorization token for RBAC
@param $host Tells the webserver which virtual host to use
@param $trim If true, then the empty properties in the JSON output are removed
@param $required A list of property names that are to remain during a trim even if they are empty
@return
@custom:openapi-tag Public
 :)
declare
    %rest:GET
    %rest:path("/v2/public/project/{$mapID}")
    %rest:header-param("JWT", "{$jwt}")
    %rest:header-param("Host", "{$host}")
    %rest:query-param("version", "{$version}", "latest")
    %rest:produces("application/octet-stream")
    %output:media-type("application/zip")
    %output:method("binary")
function v2pub:project-by-id(
            $jwt as xs:string*,
            $host as xs:string*,
            $mapID as xs:string*,
            $version as xs:string*
)
{
    let $login := login:authenticate($jwt)
    let $total-host := magutil:host($host)
    let $mapping := magutil:get-mapping-version($mapID, $version)
    let $mapping-entry := <entry name="" type="xml" method="store">{fn:serialize($mapping, map {"method": "xml" })}</entry>
    let $zip := compression:zip($mapping-entry, fn:false())
    return $zip
};

UPDATE:

I tried adding the following to the return

    return
<rest:response>
  <http:response status="200" message="Success">
    <http:header name="Content-Disposition" value="attachment; filename=test.zip"/>
  </http:response>
</rest:response>,
    $zip

But it is now telling me that $zip is not set.

UPDATE 2:

I was missing as item()+. The zip file is still not working though.

xquery version "3.1";

module namespace v2pub = "http://easymetahub.com/modules/ns/public/v2";

declare namespace rest="http://exquery.org/ns/restxq";
declare namespace http = "http://expath.org/ns/http-client";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

(:~

@param $jwt The JWT authorization token for RBAC
@param $host Tells the webserver which virtual host to use
@param $trim If true, then the empty properties in the JSON output are removed
@param $required A list of property names that are to remain during a trim even if they are empty
@return
@custom:openapi-tag Public
 :)
declare
    %rest:GET
    %rest:path("/v2/public/project/{$mapID}")
    %rest:header-param("JWT", "{$jwt}")
    %rest:header-param("Host", "{$host}")
    %rest:query-param("version", "{$version}", "latest")
    %rest:produces("application/octet-stream")
    %output:media-type("application/zip")
    %output:method("binary")
function v2pub:project-by-id(
            $jwt as xs:string*,
            $host as xs:string*,
            $mapID as xs:string*,
            $version as xs:string*
)
as item()+
{
    let $login := login:authenticate($jwt)
    let $total-host := magutil:host($host)
    let $mapping := magutil:get-mapping-version($mapID, $version)
    let $mapping-entry := <entry name="" type="xml" method="store">{fn:serialize($mapping, map {"method": "xml" })}</entry>
    let $zip := compression:zip($mapping-entry, fn:false())
    return
     (
<rest:response>
  <http:response status="200" message="Success">
    <http:header name="Content-Disposition" value="attachment; filename=test.zip"/>
  </http:response>
</rest:response>,
    $zip)
};
2

There are 2 answers

1
Loren Cahlander On BEST ANSWER

I found the fix. I was missing as item()+

xquery version "3.1";

module namespace v2pub = "http://easymetahub.com/modules/ns/public/v2";

declare namespace rest="http://exquery.org/ns/restxq";
declare namespace http = "http://expath.org/ns/http-client";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";

(:~

@param $jwt The JWT authorization token for RBAC
@param $host Tells the webserver which virtual host to use
@param $trim If true, then the empty properties in the JSON output are removed
@param $required A list of property names that are to remain during a trim even if they are empty
@return
@custom:openapi-tag Public
 :)
declare
    %rest:GET
    %rest:path("/v2/public/project/{$mapID}")
    %rest:header-param("JWT", "{$jwt}")
    %rest:header-param("Host", "{$host}")
    %rest:query-param("version", "{$version}", "latest")
    %rest:produces("application/octet-stream")
    %output:media-type("application/zip")
    %output:method("binary")
function v2pub:project-by-id(
            $jwt as xs:string*,
            $host as xs:string*,
            $mapID as xs:string*,
            $version as xs:string*
)
as item()+
{
    let $login := login:authenticate($jwt)
    let $total-host := magutil:host($host)
    let $mapping := magutil:get-mapping-version($mapID, $version)
    let $mapping-entry := <entry name="test.xml" type="xml" method="store">{fn:serialize($mapping, map {"method": "xml" })}</entry>
    let $zip := compression:zip($mapping-entry, fn:false())
    return
     (
<rest:response>
  <http:response status="200" message="Success">
    <http:header name="Content-Disposition" value="attachment; filename=test.zip"/>
  </http:response>
</rest:response>,
    $zip)
};
1
line-o On

I have not tried this with restXQ but otherwise in eXist-db I use

response:stream-binary#3

to stream binary content to clients.