如何将XQuery单文件上传函数改造为支持多文件上传?
解决MarkLogic多文件上传的XQuery改造方案
你说得对,当表单开启multiple="true"后,xdmp:get-request-field()系列函数会返回对应参数的序列值(每个上传文件对应序列里的一项),而不是单个字符串,所以fn:tokenize()肯定没用。我们可以通过循环遍历序列来处理每个上传的文件,下面是具体的改造方案:
核心思路
当多文件上传时,xdmp:get-request-field("upload")、xdmp:get-request-field-filename("upload")、xdmp:get-request-field-content-type("upload")这三个函数返回的序列是位置一一对应的——序列第N项分别对应第N个上传文件的内容、文件名、内容类型。我们可以利用XQuery的for循环,结合位置变量来绑定每个文件的相关信息,再复用你原来的单文件处理逻辑。
改造后的完整代码
declare function local:process-single-file($file as item(), $filename as xs:string, $contenttype as xs:string) as xs:string { let $extension := fn:replace($filename, '.*\.', '') let $_ := switch ($contenttype) case "text/xml" case "text/xhtml" case "text/csv" case "text/plain" case "application/json" return xdmp:document-insert($filename, xdmp:unquote($file)) case "application/octet-stream" return switch ($extension) case "gpx" return xdmp:document-insert($filename, xdmp:unquote(xdmp:quote(binary{xs:hexBinary($file)}))) default return xdmp:document-insert($filename, $file) default return xdmp:document-insert($filename, $file) return fn:concat("File '", $filename, "' uploaded successfully (Content-Type: ", $contenttype, ", Extension: ", $extension, ")") }; declare function local:uploadFiles() as xs:string* { let $files := xdmp:get-request-field("upload") let $filenames := xdmp:get-request-field-filename("upload") let $contenttypes := xdmp:get-request-field-content-type("upload") return for ($file at $pos in $files) let $filename := $filenames[$pos] let $contenttype := $contenttypes[$pos] return local:process-single-file($file, $filename, $contenttype) }; local:uploadFiles()
代码说明
- 封装单文件处理逻辑:把原来的单文件上传逻辑抽成
local:process-single-file函数,负责处理单个文件的插入,并返回上传结果信息。这样代码更模块化,也方便后续维护。 - 循环遍历多文件序列:在
local:uploadFiles函数中,通过for ($file at $pos in $files)遍历所有上传文件的内容,利用位置变量$pos从$filenames和$contenttypes序列中取出对应文件的文件名和内容类型。 - 返回批量结果:循环会返回每个文件的上传结果字符串,最终会拼接成一个结果序列返回给前端。
注意事项
- 确保你的HTML表单已经正确设置
enctype="multipart/form-data"(你提供的代码已经满足),这是文件上传的必要条件。 - 如果上传的文件数量较多,可以考虑添加错误处理逻辑(比如捕获
xdmp:document-insert可能抛出的异常,返回更友好的错误信息)。
内容的提问来源于stack exchange,提问作者Mick Remmerswaal
相关产品推荐
相关产品推荐

