odoo14前端批量下载附件(可以多个附件)模块

需求:

在项目中,将当前列表中被选中记录(一条记录可能有多个附件)的附件在前端批量下载下来,形成一个压缩包,并且通过记录表单字段值进行分类,同一个记录的附件放在以当前表单字段命名的文件夹中

应为需要多个列表使用,写成通用模式

效果:

模块主要代码:

逻辑:

先进行构思:先选中记录,点击某个按钮或动作(带防抖功能)执行 post 请求并附带选中记录的当前模型名称和ID的内容,

后端在接收到请求后,根据post附带的信息获取对应附件打包压缩发送前端,前端接收后处理数据并下载。

js请求接收代码:

编写发送和接收数据的通用js代码

odoo.define('download_document.download_function', function (require) {
  "use strict";

  function debounce(func, delay) {
    let timerId;

    return function (...args) {
      clearTimeout(timerId);

      timerId = setTimeout(function () {
        func.apply(this, args);
      }, delay);
    };
  }

  function downloadAttachments(attachment_ids, model_name) {
    console.log('attachment_ids:', attachment_ids);
    console.log('model_name:', model_name);
    if (attachment_ids.length > 0) {
      $.ajax({
        url: '/custom_module/download_attachments',
        method: 'POST',
        data: {
          attachment: JSON.stringify(attachment_ids),
          model_name: JSON.stringify(model_name),
        },
        xhrFields: {
          responseType: 'blob'
        },
        success: function (response) {
          var blob = new Blob([response], {type: 'application/zip'});
          var link = document.createElement('a');
          link.href = URL.createObjectURL(blob);
          link.download = 'attachments.zip';
          link.click();
        }
      });
    }
  }

  var debouncedDownloadAttachments = debounce(downloadAttachments, 500); 

  return {
    downloadAttachments: debouncedDownloadAttachments
  };
});

配置文件:

引入 js 文件:

<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
    <template id="assets_eas_sync" name="eas_sync" inherit_id="web.assets_backend">
        <xpath expr="." position="inside">
            <script type="text/javascript" src="/download_document/static/js/download.js"/>
        </xpath>
    </template>
</odoo>

📎__manifest__.py 文件中加入 这个xml文件

后端逻辑:

class CustomController(http.Controller):

    def delete_subfiles_and_subfolders(self, folder_path):
        for filename in os.listdir(folder_path):
            file_path = os.path.join(folder_path, filename)
            if os.path.isfile(file_path):
                os.remove(file_path)
            elif os.path.isdir(file_path):
                shutil.rmtree(file_path)

    @http.route('/custom_module/download_attachments', methods=["POST"], auth='public', type='http', csrf=False,
                website=True, cors='*')
    def download_attachments(self, **post):
        ids = list(json.loads(post.get('attachment')))
        _model_name = json.loads(post.get('model_name'))
        attachments = request.env['ir.attachment'].search([('res_model', '=', _model_name), ('res_id', 'in', ids)])
        # 创建各个文件夹路径
        absolute_path = os.path.join(os.getcwd(), 'download', _model_name,'files')
        zip_path = os.path.join(os.getcwd(), 'download', _model_name,'compressed')
        zip_filename = 'attachments.zip'

        # 判断需要的文件夹路径是否存在
        if not os.path.exists(absolute_path):
            os.makedirs(absolute_path)
        if not os.path.exists(zip_path):
            os.makedirs(zip_path)

        # 删除上一次的写入文件和对应的压缩文件
        self.delete_subfiles_and_subfolders(absolute_path)
        self.delete_subfiles_and_subfolders(zip_path)

        # 循环创建并写入文件数据
        for attachment in attachments:
            filename = attachment.res_name
            file_content = base64.b64decode(attachment.datas)
            save_path = os.path.join(absolute_path, filename)
            file_path = os.path.join(save_path, attachment.name)
            if not os.path.exists(save_path):
                os.makedirs(save_path)
            with open(file_path, 'wb') as f:
                f.write(file_content)

        attachments_file_path = os.path.join(zip_path, zip_filename)
        base_folder = os.path.basename(absolute_path)
        # 创建ZipFile对象并打开要创建的压缩包文件
        with zipfile.ZipFile(attachments_file_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk(absolute_path):
                for file in files:
                    file_path = os.path.join(root, file)
                    relative_path = os.path.relpath(file_path, absolute_path)
                    if relative_path.startswith(base_folder):
                        relative_path = relative_path[len(base_folder) + 1:]
                    zipf.write(file_path, relative_path)

        # 读取文件内容
        with open(attachments_file_path, 'rb') as file:
            file_data = file.read()
        # 创建响应对象
        response = request.make_response(file_data)
        response.mimetype = 'application/zip'
        # 设置下载文件的名称
        response.headers.set('Content-Disposition', 'attachment', filename='attachments.zip')
        return response

模块配置:

1.在需要的模块中安装该模块的依赖

2.在自己的js代码的逻辑中适当调用模块的js代码函数,列如:

odoo.define('order_coordination.download_button', function (require) {
    "use strict";
    var ListController = require('web.ListController');
	# 引入模块的js函数
    var downloadFunction = require('download_document.download_function');

    ListController.include({
        renderButtons: function ($node) {
            this._super.apply(this, arguments);
            if (this.$buttons) {
                this.$buttons.on('click', '.download_button', this.debouncedDownloadAttachments.bind(this));
            }
        },
        debouncedDownloadAttachments: function () {
            var self = this;
        	# 获取当前选中记录的ID数组
            var attachment_ids = this.getSelectedIds();
        	# 获取当前选中记录的模型名称
            var model_name = self.modelName;
        	# 执行模块的js函数
            downloadFunction.downloadAttachments(attachment_ids,model_name)

        }
    });
});
  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Odoo 是一款开源的企业资源规划软件,它提供了完整的后台管理系统和前端展示系统,同时也支持文件的存储和下载。下面就针对 Odoo 的后台与前端文件(附件)的存储与下载进行浅谈。 1. 后台文件存储 Odoo 的后台文件存储主要是通过模型字段来实现的。在模型中,我们可以定义一个二进制字段(binary field),用来存储文件的二进制数据。例如,我们可以在产品模型中添加一个图片字段,用来存储产品的图片数据。定义方式如下: ```python class Product(models.Model): _name = 'product.product' _description = 'Product' name = fields.Char(required=True) image = fields.Binary(string="Image") ``` 当我们上传一个图片时,Odoo 会将图片的二进制数据存储到这个字段中。我们可以在后台管理系统中查看和编辑这个字段的值,并可以在模板中使用这个字段来展示图片。 2. 前端文件存储 Odoo 的前端文件存储主要是通过附件(attachment)来实现的。附件可以是任何类型的文件,例如文档、图片、音频等。在 Odoo 中,我们可以在任何一个模型中添加附件字段(attachment field),用来存储附件数据。例如,我们可以在客户模型中添加一个附件字段,用来存储客户的合同文件数据。定义方式如下: ```python class ResPartner(models.Model): _name = 'res.partner' _description = 'Partner' name = fields.Char(required=True) contract = fields.Many2many('ir.attachment', string="Contract") ``` 当我们上传一个附件时,Odoo 会将附件的数据存储到 ir.attachment 表中,并将附件与当前模型记录关联起来。我们可以在后台管理系统中查看和编辑这些附件,并可以在模板中使用这些附件来提供下载链接。 3. 文件下载 Odoo 提供了多种方式来进行文件下载。在后台管理系统中,我们可以直接点击图片或附件字段来下载对应的文件。在模板中,我们可以使用 Odoo 的文件下载链接来提供下载功能。例如,我们可以在客户列表中展示客户的合同文件,并提供下载链接,代码如下: ```xml <tree string="Partners"> <field name="name"/> <field name="contract" widget="many2many_download"/> </tree> ``` 这里使用了 many2many_download widget 来展示客户的合同文件,并提供下载链接。 以上就是 Odoo 后台与前端文件(附件)的存储与下载的浅谈。Odoo 提供了灵活的文件存储和下载方式,可以满足企业级应用的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑的蜗牛..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值