v1.0.7: parser.cfm — DOCX через ZIP/XML (без POI)
This commit is contained in:
@@ -1 +1 @@
|
||||
<cfsetting showdebugoutput=no enablecfoutputonly=yes><cfoutput>OK v1.0.6</cfoutput>
|
||||
<cfsetting showdebugoutput=no enablecfoutputonly=yes><cfoutput>OK v1.0.7</cfoutput>
|
||||
|
||||
+120
-4
@@ -72,10 +72,126 @@
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
|
||||
<!--- DOCX/DOC — POI нет, пропускаем --->
|
||||
<cfelseif doc.mime_type EQ "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||
OR doc.mime_type EQ "application/msword">
|
||||
<cfset arrayAppend(errors, "DOCX/DOC parsing not available (POI not installed)")>
|
||||
<!--- DOCX — ZIP/XML (POI не нужен) --->
|
||||
<cfelseif doc.mime_type EQ "application/vnd.openxmlformats-officedocument.wordprocessingml.document">
|
||||
<cftry>
|
||||
<cfset fileBytes = binaryDecode(doc.original_bytes, "base64")>
|
||||
<cfset bais = createObject("java", "java.io.ByteArrayInputStream").init(fileBytes)>
|
||||
<cfset zis = createObject("java", "java.util.zip.ZipInputStream").init(bais)>
|
||||
|
||||
<cfset xmlStr = "">
|
||||
<cfloop condition="true">
|
||||
<cfset entry = zis.getNextEntry()>
|
||||
<cfif isNull(entry)><cfbreak></cfif>
|
||||
<cfif entry.getName() EQ "word/document.xml">
|
||||
<cftry>
|
||||
<cfset xmlBytes = zis.readAllBytes()>
|
||||
<cfset xmlStr = createObject("java", "java.lang.String").init(xmlBytes, "UTF-8")>
|
||||
<cfcatch>
|
||||
<!--- fallback: читаем через буфер --->
|
||||
<cfset baos = createObject("java", "java.io.ByteArrayOutputStream").init()>
|
||||
<cfloop condition="true">
|
||||
<cfset b = zis.read()>
|
||||
<cfif b LT 0><cfbreak></cfif>
|
||||
<cfset baos.write(b)>
|
||||
</cfloop>
|
||||
<cfset xmlStr = createObject("java", "java.lang.String").init(baos.toByteArray(), "UTF-8")>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfbreak>
|
||||
</cfif>
|
||||
<cfset zis.closeEntry()>
|
||||
</cfloop>
|
||||
<cfset zis.close()>
|
||||
<cfset bais.close()>
|
||||
|
||||
<cfif NOT len(xmlStr)>
|
||||
<cfset arrayAppend(errors, "DOCX: word/document.xml not found in ZIP")>
|
||||
<cfelse>
|
||||
<cfset docXml = xmlParse(xmlStr)>
|
||||
<cfset ns = "http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
||||
|
||||
<!--- Ищем body: или с namespace или без --->
|
||||
<cfset body = "">
|
||||
<cftry>
|
||||
<cfset body = xmlSearch(docXml, "//:body")>
|
||||
<cfcatch>
|
||||
<cfset body = xmlSearch(docXml, "//*[local-name()='body']")>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
|
||||
<cfif arrayLen(body) GT 0>
|
||||
<cfset body = body[1]>
|
||||
<cfloop array="#body.XmlChildren#" index="child">
|
||||
<cfset localName = child.XmlName>
|
||||
<cfif localName EQ "p" OR right(localName, 2) EQ ":p">
|
||||
<!--- Параграф: собираем текст из всех w:t --->
|
||||
<cfset paraText = "">
|
||||
<cftry>
|
||||
<cfset textNodes = xmlSearch(child, "//:t")>
|
||||
<cfcatch>
|
||||
<cfset textNodes = xmlSearch(child, "//*[local-name()='t']")>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfloop array="#textNodes#" index="tn">
|
||||
<cfset paraText &= tn.XmlText>
|
||||
</cfloop>
|
||||
<cfset paraText = trim(paraText)>
|
||||
<cfif len(paraText)>
|
||||
<cfset arrayAppend(elements, {type: "paragraph", style: "", text: paraText, page: 0})>
|
||||
</cfif>
|
||||
<cfelseif localName EQ "tbl" OR right(localName, 4) EQ ":tbl">
|
||||
<!--- Таблица --->
|
||||
<cfset rows = []>
|
||||
<cftry>
|
||||
<cfset trNodes = xmlSearch(child, "//:tr")>
|
||||
<cfcatch>
|
||||
<cfset trNodes = xmlSearch(child, "//*[local-name()='tr']")>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfloop array="#trNodes#" index="trNode">
|
||||
<cfset row = []>
|
||||
<cftry>
|
||||
<cfset tcNodes = xmlSearch(trNode, ".//:tc")>
|
||||
<cfcatch>
|
||||
<cfset tcNodes = xmlSearch(trNode, ".//*[local-name()='tc']")>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfloop array="#tcNodes#" index="tcNode">
|
||||
<cfset cellText = "">
|
||||
<cftry>
|
||||
<cfset tNodes = xmlSearch(tcNode, ".//:t")>
|
||||
<cfcatch>
|
||||
<cfset tNodes = xmlSearch(tcNode, ".//*[local-name()='t']")>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
<cfloop array="#tNodes#" index="tNode">
|
||||
<cfset cellText &= tNode.XmlText>
|
||||
</cfloop>
|
||||
<cfset arrayAppend(row, trim(cellText))>
|
||||
</cfloop>
|
||||
<cfif arrayLen(row) GT 0>
|
||||
<cfset arrayAppend(rows, row)>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<cfif arrayLen(rows) GT 0>
|
||||
<cfset arrayAppend(elements, {type: "table", rows: rows, page: 0})>
|
||||
</cfif>
|
||||
</cfif>
|
||||
</cfloop>
|
||||
<cfelse>
|
||||
<cfset arrayAppend(errors, "DOCX: body not found in document.xml")>
|
||||
</cfif>
|
||||
</cfif>
|
||||
|
||||
<cfcatch>
|
||||
<cfset arrayAppend(errors, "DOCX: " & cfcatch.message)>
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
|
||||
<!--- .doc — старый формат, пропускаем --->
|
||||
<cfelseif doc.mime_type EQ "application/msword">
|
||||
<cfset arrayAppend(errors, ".doc parsing not available (use libreoffice to convert)")>
|
||||
|
||||
<!--- TXT — plain text --->
|
||||
<cfelseif doc.mime_type EQ "text/plain" OR doc.mime_type EQ "application/octet-stream">
|
||||
|
||||
Reference in New Issue
Block a user