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