Package: odoo-addon-fs-file
This addon defines a new field typeFSFilewhich is a file field that stores
a file in an external filesystem instead of the odoo’s filestore. This is useful for
large files that you don’t want to store in the filestore. Moreover, the field
value provides you an interface to access the file’s contents and metadata.ImportantThis is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.More details on development statusTable of contentsUsageChangelog16.0.1.0.6 (2024-02-23)16.0.1.0.5 (2023-11-30)16.0.1.0.4 (2023-10-17)16.0.1.0.3 (2023-10-05)16.0.1.0.1 (2023-09-29)Bug TrackerCreditsAuthorsContributorsMaintainersUsageThe new fieldFSFilehas been developed to allows you to store files
in an external filesystem storage. Its design is based on the following
principles:The content of the file must be read from the filesystem only when
needed.It must be possible to manipulate the file content as a stream by default.Unlike Odoo’s Binary field, the content is the raw file content by default
(no base64 encoding).To allows to exchange the file content with other systems, writing the
content as base64 is possible. The read operation will return a json
structure with the filename, the mimetype, the size and a url to download the file.This design allows to minimize the memory consumption of the server when
manipulating large files and exchanging them with other systems through
the default jsonrpc interface.Concretely, this design allows you to write code like this:fromIOimportBytesIOfromodooimportmodels,fieldsfromodoo.addons.fs_file.fieldsimportFSFileclassMyModel(models.Model):_name='my.model'name=fields.Char()file=FSFile()# Create a new record with a raw contentmy_model=MyModel.create({'name':'My File','file':BytesIO(b"content"),})assert(my_model.file.read()==b"content")# Create a new record with a base64 encoded contentmy_model=MyModel.create({'name':'My File','file':b"content".encode('base64'),})assert(my_model.file.read()==b"content")# Create a new record with a file contentmy_model=MyModel.create({'name':'My File','file':open('my_file.txt','rb'),})assert(my_model.file.read()==b"content")assert(my_model.file.name=="my_file.txt")# create a record with a file content as base64 encoded and a filename# This method is useful to create a record from a file uploaded# through the web interface.my_model=MyModel.create({'name':'My File','file':{'filename':'my_file.txt','content':base64.b64encode(b"content"),},})assert(my_model.file.read()==b"content")assert(my_model.file.name=="my_file.txt")# write the content of the file as base64 encoded and a filename# This method is useful to update a record from a file uploaded# through the web interface.my_model.write({'file':{'name':'my_file.txt','file':base64.b64encode(b"content"),},})# the call to read() will return a json structure with the filename,# the mimetype, the size and a url to download the file.info=my_model.file.read()assert(info["file"]=={"filename":"my_file.txt","mimetype":"text/plain","size":7,"url":"/web/content/1234/my_file.txt",})# use the field as a file stream# In such a case, the content is read from the filesystem without being# stored in memory.withmy_model.file.open("rb) as f:assert(f.read()==b"content")# use the field as a file stream to write the content# In such a case, the content is written to the filesystem without being# stored in memory. This kind of approach is useful to manipulate large# files and to avoid to use too much memory.# Transactional behaviour is ensured by the implementation!withmy_model.file.open("wb")asf:f.write(b"content")Changelog16.0.1.0.6 (2024-02-23)BugfixesFixes the creation of empty files.Before this change, the creation of empty files resulted in a constraint
violation error. This was due to the fact that even if a name was given
to the file it was not preserved into the FSFileValue object if no content
was given. As result, when the corresponding ir.attachment was created in
the database, the name was not set and the ‘required’ constraint was violated. (#341)16.0.1.0.5 (2023-11-30)BugfixesEnsure the cache is properly set when a new value is assigned to a FSFile field.
If the field is stored the value to the cache must be a FSFileValue object
linked to the attachment record used to store the file. Otherwise the value
must be one given since it could be the result of a compute method. (#290)16.0.1.0.4 (2023-10-17)BugfixesBrowse attachment with sudo() to avoid read access errorsIn models that have a multi fs image relation, a new line
in form will trigger onchanges and will call the fs.file model
‘convert_to_cache()’ method that will try to browse the attachment
with user profile that could have no read rights on attachment model. (#288)16.0.1.0.3 (2023-10-05)BugfixesFix themimetypeproperty onFSFileValueobjects.Themimetypevalue is computed as follow:If an attachment is set, the mimetype is taken from the attachment.If no attachment is set, the mimetype is guessed from the name of the file.If the mimetype cannot be guessed from the name, the mimetype is guessed from
the content of the file. (#284)16.0.1.0.1 (2023-09-29)FeaturesAdd aurl_pathproperty on theFSFileValueobject. This property
allows you to easily get access to the relative path of the file on
the filesystem. This value is only available if the filesystem storage
is configured with aBase URLvalue. (#281)BugfixesTheurl_path,urlandinternal_urlproperties on theFSFileValueobject returnNoneif the information is not available (instead ofFalse).Theurlproperty on theFSFileValueobject returns the filesystem url nor
the url field of the attachment. (#281)Bug TrackerBugs are tracked onGitHub Issues.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomedfeedback.Do not contact contributors directly about support or help with technical issues.CreditsAuthorsACSONE SA/NVContributorsLaurent Mignon <laurent.mignon@acsone.eu>
Marie Lejeune <marie.lejeune@acsone.eu>
Hugues Damry <hughes.damry@acsone.eu>MaintainersThis module is maintained by the OCA.OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.Currentmaintainer:This module is part of theOCA/storageproject on GitHub.You are welcome to contribute. To learn how please visithttps://odoo-community.org/page/Contribute.