Skip to content

Instantly share code, notes, and snippets.

@peterstadler
Created November 15, 2017 20:27
Show Gist options
  • Save peterstadler/fd6ed3b082f0bc602597191fc9153e17 to your computer and use it in GitHub Desktop.
Save peterstadler/fd6ed3b082f0bc602597191fc9153e17 to your computer and use it in GitHub Desktop.
xquery version "1.0";
declare function local:upload() {
let $filename := request:get-uploaded-file-name('file')
return
<results>
<message>File {$filename} has been stored.</message>
</results>
};
local:upload()
@peterstadler
Copy link
Author

  1. store that XQuery as test.xql in e.g. /db/apps/test/test.xql
  2. send a file to that XQuery: curl -F "file=@/path/to/file" http://localhost:8080/exist/apps/test/test.xql
  3. result should be
<results>
    <message>File test.xml has been stored.</message>
</results>

@tonyahowe
Copy link

Hmmm. I am getting the same exact problem:

MacBook-Pro-7:Shared tonya-mariehowe$ curl -F "file=/testfile.xml" http://localhost:8080/exist/apps/test/test.xql
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 400 SAX exception while parsing request: Content is not allowed in prolog.</title>
</head>
<body><h2>HTTP ERROR 400</h2>
<p>Problem accessing /exist/apps/test/test.xql. Reason:
<pre>    SAX exception while parsing request: Content is not allowed in prolog.</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.9.v20160517</a><hr/>

</body>
</html>
MacBook-Pro-7:Shared tonya-mariehowe$ 

Also: cool to see how that works!!

@tonyahowe
Copy link

Oh, no! I see one problem--my path is not right. I corrected that in the curl command and it worked!! Let me see if I can figure it out now. I'll report back!

@tonyahowe
Copy link

tonyahowe commented Nov 15, 2017

Okay, so this test case works, but nothing is uploaded. Looking at it, it seems like it's not meant to be uploaded, just to see whether there's a problem at this point or that--right? I tweaked the URL of the local install to ensure that the path was correct, and I got an error message that seemed promising:

err:XPTY0004 checking function parameter 3 in call xmldb:store(untyped-value-check[xs:string, $collection], untyped-value-check[xs:string, $filename], request:get-uploaded-file-data("file")): XPTY0004: The actual cardinality for parameter 3 does not match the cardinality declared in the function's signature: xmldb:store($collection-uri as xs:string, $resource-name as xs:string?, $contents as item()) xs:string?. Expected cardinality: exactly one, got 0. [at line 406, column 51, source: /db/apps/NiC/modules/app.xql]

This seems to suggest that there was no filename to be passed. BUT, when I returned to the upload page and re-submitted the test file, I get the same old problem message--with the right path, this time:

Problem accessing /exist/apps/NiC/form1.html. Reason: SAX exception while parsing request: Content is not allowed in prolog.

So I'm back to square one. Though there might still be a path problem somewhere.

@peterstadler
Copy link
Author

Ah, I think now I see: You are piping request:get-uploaded-file-data("file") directly to xmldb:store() but the return type of the former is as xs:base64Binary* and the latter expects it to be a "either a node, an xs:string, a Java file object or an xs:anyURI" (from the function documentation).

So you have to pipe the result through util:binary-to-string() first!

@tonyahowe
Copy link

tonyahowe commented Nov 16, 2017

Something like this?

declare function app:upload($node as node(), $model as map(*)) {
   
let $collection := 'db/apps/NiC/inReview'
let $filename := request:get-uploaded-file-name('file')
let $file := util:binary-to-string($filename)

(: make sure you use the right user permissions that has write access to this collection :)
let $login := xmldb:login($collection, 'username', 'superhardpassword')
let $store as xs:string? := xmldb:store($collection, $filename, request:get-uploaded-file-data($file), 'application/octet-stream')
(:let $store := xmldb:store($collection, $filename, request:get-uploaded-file-data('file')):) 

I'm sure the syntax is incorrect--I figured I'd try to break something, but I am still receiving the "problem accessing form1.html" SAX exception. So I'm not sure the app:upload is even being run. I'll continue to play with it!

@peterstadler
Copy link
Author

(untested)

declare function app:upload($node as node(), $model as map(*)) {
   
let $collection := 'db/apps/NiC/inReview'
let $filename := request:get-uploaded-file-name('file')
let $file := util:binary-to-string(request:get-uploaded-file-data('file'))

(: make sure you use the right user permissions that has write access to this collection :)
let $login := xmldb:login($collection, 'username', 'superhardpassword')
let $store as xs:string? := xmldb:store($collection, $filename, $file)
(:let $store := xmldb:store($collection, $filename, request:get-uploaded-file-data('file')):) 

@tonyahowe
Copy link

Okay, so I got it to work--but in a very strange way. Do you have any insight? I think it's a controller/path issue, but why it works now and doesn't if I trust the controller to do what it's supposed to do is frustrating to no end: https://stackoverflow.com/questions/47182646/uploading-documents-to-a-server-using-xql-exist-db

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment