Wiki source code of Filesystem store
Version 3.1 by Thomas Mortagne on 2024/05/23
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{box cssClass="floatinginfobox" title="**Contents**"}}{{toc start="2"/}}{{/box}} | ||
2 | |||
3 | By default in XWiki the content of attachments and deleted attachment and documents are stored in what we call the "filesystem store". By default it's located in ##<permanentdir>/store/file##. | ||
4 | |||
5 | It's a simple file based storage in which documents and attachments references are (md5) hashed, to avoid problems with various limited (in terms of encoding and path size) file systems. | ||
6 | |||
7 | For example the attachment ##XWikiLogo.png## in document ##Sandbox.WebHome## is stored in the following location: ##/1/0/5d42329a923e687f5dff4887d80098/attachments/9/2/0bc685fa0da28168319c0126def81b##. | ||
8 | |||
9 | {{box title="And where is my entity located ?"}} | ||
10 | {{velocity}} | ||
11 | {{html}} | ||
12 | <form> | ||
13 | <input type="text" name="reference"#if($request.reference) value="$escapetool.xml($request.reference)#end"/> | ||
14 | <button name="serialize_document">Document</button> | ||
15 | <button name="serialize_attachment">Attachment</button> | ||
16 | </form> | ||
17 | {{/html}} | ||
18 | {{/velocity}} | ||
19 | |||
20 | {{groovy}} | ||
21 | def hash(str) | ||
22 | { | ||
23 | md5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(str) | ||
24 | println "1. It's then md5 hashed (##${md5}##)." | ||
25 | |||
26 | char0 = md5.charAt(0) | ||
27 | println "1. A first folder is created with the first character of the hash (##${char0}##)." | ||
28 | |||
29 | char1 = md5.charAt(1) | ||
30 | println "1. A second folder is created with the second character of the hash (##${char1}##)." | ||
31 | |||
32 | charn = md5.substring(2) | ||
33 | println "1. A third folder is created with the remaining characters (##${charn}##)." | ||
34 | |||
35 | return "**$char0**/**$char1**/**$charn**" | ||
36 | } | ||
37 | |||
38 | def encodeDocument(documentReference) { | ||
39 | path = "" | ||
40 | if (documentReference.root.type == org.xwiki.model.EntityType.WIKI) { | ||
41 | println "1. A folder with the wiki name (##${documentReference.root.name}##) is created." | ||
42 | path = documentReference.root.name | ||
43 | } | ||
44 | |||
45 | localuid = services.component.getInstance(org.xwiki.model.reference.EntityReferenceSerializer.TYPE_STRING, "local/uid").serialize(documentReference) | ||
46 | println "1. The document reference is serialized using the local uid serializer (##${localuid}##)." | ||
47 | |||
48 | path += "/" + hash(localuid) | ||
49 | |||
50 | return path; | ||
51 | } | ||
52 | |||
53 | def encodeAttachment(attachmentReference) { | ||
54 | path = "" | ||
55 | if (reference.parent) { | ||
56 | path = encodeDocument(attachmentReference.parent) | ||
57 | } | ||
58 | |||
59 | path += "/attachments" | ||
60 | println "1. An ##attachments## folder is created." | ||
61 | |||
62 | name = attachmentReference.name | ||
63 | println "1. The attachment name (##$name##) is extracted from the reference." | ||
64 | |||
65 | path += "/" + hash(name) + "" | ||
66 | } | ||
67 | |||
68 | if (request.serialize_document != null) { | ||
69 | reference = services.component.getInstance(org.xwiki.model.reference.EntityReferenceResolver.TYPE_STRING, "relative").resolve(request.reference, org.xwiki.model.EntityType.DOCUMENT) | ||
70 | |||
71 | println "{{info}}" | ||
72 | path = encodeDocument(reference) | ||
73 | println "{{/info}}" | ||
74 | |||
75 | println "" | ||
76 | print "The final path of the folder which contains the content of this attachment is ##$path##." | ||
77 | } else if (request.serialize_attachment != null) { | ||
78 | reference = services.component.getInstance(org.xwiki.model.reference.EntityReferenceResolver.TYPE_STRING, "relative").resolve(request.reference, org.xwiki.model.EntityType.ATTACHMENT) | ||
79 | |||
80 | println "{{info}}" | ||
81 | path = encodeAttachment(reference) | ||
82 | println "{{/info}}" | ||
83 | |||
84 | println "" | ||
85 | print "The final path of the folder which contains the content of this document is ##$path##." | ||
86 | } | ||
87 | {{/groovy}} | ||
88 | {{/box}} | ||
89 | |||
90 | == Attachments and deleted attachments | ||
91 | |||
92 | By default, inside the attachment folder, you will find both the current version of the attachment and its history. The file name is always ##f##, it's then optionally followed by the version (when it's a piece of the history) and the original file extension. | ||
93 | |||
94 | * ##f.png## | ||
95 | * ##fv1.1.png## | ||
96 | * ##fv2.1.png## | ||
97 | |||
98 | {{version since="16.4.0"}} | ||
99 | Most of the time, instead of the current version of the attachment, a "link" is created. It's a file named ##f.<ext>.lnk## which contains the relative path it's representing. In standard condition, it always points to the latest version of the attachment. | ||
100 | {{/version}} | ||
101 | |||
102 | * ##f.png.lnk## {{info}}contains the string ##fv2.1.png##{{/info}} | ||
103 | * ##fv1.1.png## | ||
104 | * ##fv2.1.png## | ||
105 | |||
106 | == Deleted attachments | ||
107 | |||
108 | |||
109 | |||
110 | == Deleted documents |