-
-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by lmignon
- Loading branch information
Showing
65 changed files
with
5,131 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
======= | ||
Fs File | ||
======= | ||
|
||
.. | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! source digest: sha256:cec7431f1becb99516793e51833fe9606ccd7459d148d15df61b03c14de1f6e4 | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png | ||
:target: https://odoo-community.org/page/development-status | ||
:alt: Alpha | ||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png | ||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github | ||
:target: https://github.com/OCA/storage/tree/17.0/fs_file | ||
:alt: OCA/storage | ||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png | ||
:target: https://translation.odoo-community.org/projects/storage-17-0/storage-17-0-fs_file | ||
:alt: Translate me on Weblate | ||
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png | ||
:target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=17.0 | ||
:alt: Try me on Runboat | ||
|
||
|badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
||
This addon defines a new field type FSFile which 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. | ||
|
||
.. IMPORTANT:: | ||
This 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 status <https://odoo-community.org/page/development-status>`_ | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Usage | ||
===== | ||
|
||
The new field **FSFile** has 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: | ||
|
||
.. code:: python | ||
from IO import BytesIO | ||
from odoo import models, fields | ||
from odoo.addons.fs_file.fields import FSFile | ||
class MyModel(models.Model): | ||
_name = 'my.model' | ||
name = fields.Char() | ||
file = FSFile() | ||
# Create a new record with a raw content | ||
my_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 content | ||
my_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 content | ||
my_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. | ||
with my_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! | ||
with my_model.file.open("wb") as f: | ||
f.write(b"content") | ||
Changelog | ||
========= | ||
16.0.1.0.6 (2024-02-23) | ||
----------------------- | ||
**Bugfixes** | ||
- Fixes 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 <https://github.com/OCA/storage/issues/341>`__) | ||
16.0.1.0.5 (2023-11-30) | ||
----------------------- | ||
**Bugfixes** | ||
- Ensure 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 <https://github.com/OCA/storage/issues/290>`__) | ||
16.0.1.0.4 (2023-10-17) | ||
----------------------- | ||
**Bugfixes** | ||
- Browse attachment with sudo() to avoid read access errors | ||
In 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 <https://github.com/OCA/storage/issues/288>`__) | ||
16.0.1.0.3 (2023-10-05) | ||
----------------------- | ||
**Bugfixes** | ||
- Fix the *mimetype* property on *FSFileValue* objects. | ||
The *mimetype* value 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 <https://github.com/OCA/storage/issues/284>`__) | ||
16.0.1.0.1 (2023-09-29) | ||
----------------------- | ||
**Features** | ||
- Add a *url_path* property on the *FSFileValue* object. 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 a *Base URL* value. | ||
(`#281 <https://github.com/OCA/storage/issues/281>`__) | ||
**Bugfixes** | ||
- The *url_path*, *url* and *internal_url* properties on the | ||
*FSFileValue* object return *None* if the information is not | ||
available (instead of *False*). | ||
The *url* property on the *FSFileValue* object returns the filesystem | ||
url nor the url field of the attachment. | ||
(`#281 <https://github.com/OCA/storage/issues/281>`__) | ||
Bug Tracker | ||
=========== | ||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/storage/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 welcomed | ||
`feedback <https://github.com/OCA/storage/issues/new?body=module:%20fs_file%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
Do not contact contributors directly about support or help with technical issues. | ||
Credits | ||
======= | ||
Authors | ||
------- | ||
* ACSONE SA/NV | ||
Contributors | ||
------------ | ||
- Laurent Mignon <laurent.mignon@acsone.eu> | ||
- Marie Lejeune <marie.lejeune@acsone.eu> | ||
- Hugues Damry <hughes.damry@acsone.eu> | ||
- Nguyen Minh Chien <chien@trobz.com> | ||
Maintainers | ||
----------- | ||
This module is maintained by the OCA. | ||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
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. | ||
.. |maintainer-lmignon| image:: https://github.com/lmignon.png?size=40px | ||
:target: https://github.com/lmignon | ||
:alt: lmignon | ||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__: | ||
|maintainer-lmignon| | ||
This module is part of the `OCA/storage <https://github.com/OCA/storage/tree/17.0/fs_file>`_ project on GitHub. | ||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Copyright 2023 ACSONE SA/NV | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
{ | ||
"name": "Fs File", | ||
"summary": """ | ||
Field to store files into filesystem storages""", | ||
"version": "17.0.1.0.0", | ||
"license": "AGPL-3", | ||
"author": "ACSONE SA/NV,Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/storage", | ||
"depends": ["fs_attachment"], | ||
"data": [], | ||
"demo": [], | ||
"maintainers": ["lmignon"], | ||
"development_status": "Alpha", | ||
"assets": { | ||
"web.assets_backend": [ | ||
"fs_file/static/src/**/*", | ||
], | ||
}, | ||
} |
Oops, something went wrong.