MarkLogic上传器误将XBRL文档识别为application/octet-stream问题咨询
问题:XBRL/XML文档被MarkLogic上传器识别为
application/octet-stream 我维护的MarkLogic文件上传器大部分时候运行正常,核心XQuery代码如下:
declare function local:uploadFile() { for $file at $pos in xdmp:get-request-field("upload") let $filename := xdmp:get-request-field-filename("upload")[$pos] let $contenttype := xdmp:get-request-field-content-type("upload")[$pos] let $extension := fn:replace($filename, '.*\.', '')[$pos] let $insert := 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, contenttype: ",$contenttype," extension: ",$extension) };
但最近上传明确是XML/XBRL类型的文档时,比如下面这两份示例,上传器会把它们识别为application/octet-stream,而非预期的XML类型:
第一份文档片段:
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="http://www.companieshouse.gov.uk/ef/xbrl/uk/fr/gaap/ae/2009-06-21/stylesheet/CH-AE-dormant-stylesheet.xsl"?> <xbrl xmlns="http://www.xbrl.org/2003/instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ae="http://www.companieshouse.gov.uk/ef/xbrl/uk/fr/gaap/ae/2009-06-21" xmlns:gc="http://www.xbrl.org/uk/fr/gcd/2004-12-01" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:iso4217="http://www.xbrl.org/2003/iso4217" xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:pt="http://www.xbrl.org/uk/fr/gaap/pt/2004-12-01" xmlns:xbrli="http://www.xbrl.org/2003/instance" xmlns:xlink="http://www.w3.org/1999/xlink"> <link:schemaRef xlink:arcrole="http://www.w3.org/1999/xlink/properties/linkbase" xlink:href="http://www.companieshouse.gov.uk/ef/xbrl/uk/fr/gaap/ae/2009-06-21/uk-gaap-ae-2009-06-21.xsd" xlink:type="simple"/> <ae:CompanyDormant contextRef="y2017">true</ae:CompanyDormant> <!-- 省略部分内容 --> </xbrl>
第二份文档头部:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xbrli:xbrl xmlns:xbrli="http://www.xbrl.org/2003/instance" xml:lang="nl" xmlns:kvk-i="http://www.nltaxonomie.nl/nt12/kvk/20171213/dictionary/kvk-data" xmlns:venj-bw2-dm="http://www.nltaxonomie.nl/nt12/venj/20171213/dictionary/venj-bw2-domains" xmlns:venj-bw2-i="http://www.nltaxonomie.nl/nt12/venj/20171213/dictionary/venj-bw2-data" xmlns:rj-i="http://www.nltaxonomie.nl/nt12/rj/20171213/dictionary/rj-data" xmlns:rj-t="http://www.nltaxonomie.nl/nt12/rj/20171213/dictionary/rj-tuples" xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:nl-cd="http://www.nltaxonomie.nl/nt12/sbr/20170515/dictionary/nl-common-data" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xbrldi="http://xbrl.org/2006/xbrldi" xmlns:iso4217="http://www.xbrl.org/2003/iso4217" xmlns:venj-bw2-dim="http://www.nltaxonomie.nl/nt12/venj/20171213/dictionary/venj-bw2-axes"> <link:schemaRef xlink:type="simple" xlink:href="http://www.nltaxonomie.nl/nt12/kvk/20171213/entrypoints/kvk-rpt-jaarverantwoording-2017-nlgaap-middelgroot-publicatiestukken.xsd"/> <xbrli:context id="FY17d"> <xbrli:entity> <xbrli:identifier scheme="http://www.kvk.nl/kvk-id">30267975</xbrli:identifier> </xbrli:entity> <xbrli:period> <xbrli:startDate>2017-01-01</xbrli:startDate> <xbrli:endDate>2017-12-31</xbrli:endDate> </xbrli:period> </xbrli:context> <!-- 省略部分内容 --> </xbrli:xbrl>
想请教这是什么原因,以及怎么解决?
原因分析
这个问题的核心在于你依赖的xdmp:get-request-field-content-type()获取的是客户端(浏览器/上传工具)发送的HTTP Content-Type头,而不是MarkLogic主动检测的文件内容类型:
- 很多操作系统或上传工具不会默认将
.xbrl扩展名映射到XML类的MIME类型(比如text/xml或application/xml),当客户端识别不出文件类型时,就会发送默认的application/octet-stream(二进制流)类型。 - 即使是XML文件,如果客户端的MIME映射表中没有对应扩展名的规则,也会被当作二进制流处理。
- 不同浏览器、上传工具的MIME映射逻辑有差异,这就导致同一文件在不同环境下可能被识别为不同的Content-Type。
解决方案
我们可以通过多维度判断来确保XML/XBRL文件被正确处理,而不是只依赖客户端发送的Content-Type:
1. 修改上传器XQuery逻辑,增加扩展名和内容检测
我调整了你的核心代码,加入了以下优化:
- 优先检测文件内容开头是否为XML声明(
<?xml),从内容层面确保XML文件被识别 - 增加对
.xml、.xbrl扩展名的判断(转小写避免大小写问题) - 补充了
application/xml、application/xbrl+xml这两个常见的XML/XBRL MIME类型
修改后的代码:
declare function local:uploadFile() { for $file at $pos in xdmp:get-request-field("upload") let $filename := xdmp:get-request-field-filename("upload")[$pos] let $contenttype := xdmp:get-request-field-content-type("upload")[$pos] let $extension := fn:lower-case(fn:replace($filename, '.*\.', ''))[$pos] let $isXmlContent := fn:starts-with(xdmp:quote($file), '<?xml') let $insert := if ($isXmlContent or $extension = ("xml", "xbrl") or $contenttype = ("text/xml", "text/xhtml", "application/xml", "application/xbrl+xml", "text/csv", "text/plain", "application/json")) then xdmp:document-insert($filename, xdmp:unquote($file)) else if ($contenttype = "application/octet-stream") then switch ($extension) case "gpx" return xdmp:document-insert($filename, xdmp:unquote(xdmp:quote(binary{xs:hexBinary($file)}))) default return xdmp:document-insert($filename, $file) else xdmp:document-insert($filename, $file) return fn:concat("file '",$filename,"' uploaded, contenttype: ",$contenttype," extension: ",$extension) };
2. 辅助优化(可选)
- 如果是浏览器上传场景,可以指导用户在操作系统中配置
.xbrl扩展名的MIME映射,比如在Windows中通过注册表添加映射,或者在macOS中修改文件关联。 - 如果使用自定义上传工具,可以在工具中主动设置正确的Content-Type头(比如上传
.xbrl文件时指定application/xbrl+xml)。
内容的提问来源于stack exchange,提问作者Mick Remmerswaal
相关产品推荐
相关产品推荐

