当前位置: 首页 > article >正文

【odoo18-文件管理】在uniapp上访问odoo系统上的图片

在uniapp上访问odoo系统上的图片

1、以url的形式访问
a:以odoo本身的域名,比如http://127.0.0.1:8069/web/image/product.template/3/image_128?unique=1740380422000,这种方式需要解决跨域的问题。
在这里插入图片描述

b:以文件服务器的形式,比如http://111.229.103.209/files/
在这里插入图片描述
2、odoo以Base64格式返回给uniapp,使用 Vue 的数据绑定来动态更新 src 属性。Base64 编码的图片会增大数据体积(大约增加 33%),对于大图片或大量图片,可能会影响性能和加载时间。

<template>
  <view>
    <image :src="dynamicBase64Image" style="width: 100px; height: 100px;"></image>
  </view>
</template>

<script>
export default {
  data() {
    return {
      dynamicBase64Image: ''
    };
  },
  methods: {
    fetchBase64Image() {
      // 假设这里通过 API 获取 Base64 编码的图片
      uni.request({
        url: 'https://example.com/api/get-base64-image',
        success: (res) => {
          this.dynamicBase64Image = res.data.base64Image;
        }
      });
    }
  },
  onLoad() {
    this.fetchBase64Image();
  }
};
</script>

最终选择了以文件服务器的形式来访问。
服务器环境:腾讯云服务器ubuntu22.04

1.使用 Nginx 托管静态文件

1.1.nginx安装

sudo apt-get install nginx # 安装nginx
sudo service nginx restart # 重启nginx

1.2.nginx环境配置

cd /etc/nginx/ # 进入nginx目录,可以通过ls查看有哪些文件
cd sites-available # 进入sites-available
# 备份一个default
sudo cp default default.bak
sudo vim default

其中location /files就是文件共享目录

server {
    listen 80;
    server_name 111.229.103.209;  # 你的域名或服务器IP
    # 静态文件托管目录
    location /files {
        alias /etc/odoo/filestore;  # 你的文件存储路径
        autoindex on;          # 可选:开启目录浏览
    }

    location / {
        proxy_redirect     off;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_read_timeout 900;  # 根据需要调整超时时间
        proxy_connect_timeout 900;  # 根据需要调整超时时间
        proxy_pass         http://127.0.0.1:8069;  # Odoo的默认端口是8069
    }

    location /longpolling {
        proxy_redirect     off;
        proxy_set_header   Host             $host;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_read_timeout 36000s;  # 长轮询可能需要较长的超时时间
        proxy_pass         http://127.0.0.1:8072;  # Odoo的长轮询端口通常是8072
    }

    # 如果需要HTTPS,请添加SSL配置段(略)
}

1.3.文件效果

在这里插入图片描述
在这里插入图片描述

2.odoo对静态文件的读写

2.1.odoo之ir.attachment

以产品图片为例:
在这里插入图片描述
odoo的ir.attachment有3层结构,这里的文件是图片。
1、文件本身对应了一个附件,用于存储文件本身,对于相同的文件,checksum和store_fname是相同的。
2、文件对应了一个webp附件,用于文件的附件地址。
3、产品图片,比如image_1920指向了文件的地址。对于image_1920、……、image_128,如果图片较小,odoo不会压缩图片,都会对应同一张图片;如果文件较大,odoo会根据尺寸限制压缩图片,不同尺寸的image会指向不同的图片地址。
在这里插入图片描述

2.2.静态文件的读写

# -*- coding: utf-8 -*-
import os
import base64
import binascii
import urllib.parse
from odoo import api, fields, models, _, _lt
from odoo.exceptions import UserError
import logging
_logger = logging.getLogger(__name__)


class IrAttachment(models.AbstractModel):
    _inherit = 'ir.attachment'

    attachment_url = fields.Char('Attachment URL', help="The URL of the file in the remote server")

    def _is_image_mimetype(self):
        """判断是否为图片类型"""
        return self.mimetype and (self.mimetype == 'image/jpeg' or self.mimetype == 'image/png')
        # return True

    def _sync_image_to_nginx(self, datas, filename):
        """同步图片到Nginx目录"""
        nginx_dir = self.env['ir.config_parameter'].sudo().get_param('attachment.dir', '/etc/odoo/filestore')
        # 获取数据库名(替换非法字符)
        # nginx_dir = odoo.tools.config['data_dir']
        db_name = self.env.cr.dbname.replace('/', '_').replace('\\', '_')
        # 获取模型名(替换点号为下划线)
        nginx_dir += f'/{db_name}/files/'
        base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
        url_parse = urllib.parse.urlparse(base_url)
        attachment_url = url_parse.scheme + '://' + url_parse.hostname + f'/{db_name}/files/'
        if not os.path.exists(nginx_dir):
            os.makedirs(nginx_dir, exist_ok=True)
            os.chmod(nginx_dir, 0o755)  # 确保目录权限

        file_path = os.path.join(nginx_dir, filename)
        try:
            with open(file_path, 'wb') as f:
                f.write(datas)
            _logger.info(f"图片已同步到Nginx目录: {file_path}")
            return attachment_url
        except Exception as e:
            _logger.error(f"同步失败: {str(e)}")
            return False

    @api.model_create_multi
    def create(self, vals_list):
        res_ids = super().create(vals_list)
        for index in range(len(res_ids)):
            vals = vals_list[index]
            res_id = res_ids[index]
            description = vals.get('description', '')
            if not res_id.mimetype or not res_id.mimetype.startswith('image') or (description and description.startswith('resize')):
                continue
            store_fname = res_id.store_fname
            attachment_id = self.env['ir.attachment']
            if store_fname:
                attachment_id = self.env['ir.attachment'].search([
                    ('id', '!=', res_id.id),
                    ('res_model', '=', 'ir.attachment'),
                    ('store_fname', '=', store_fname),
                ])
            if attachment_id and attachment_id.attachment_url:
                res_id.write({
                    'attachment_url': attachment_id.attachment_url
                })
                continue
            if not res_id._is_image_mimetype():
                continue
            if not vals.get('res_id'):
                continue
            attachment_id = self.env['ir.attachment'].sudo().browse(vals.get('res_id'))
            datas = vals.get('datas')
            if not datas or not attachment_id:
                continue
            # Base64解码
            file_data = base64.b64decode(datas) or False
            # 同步到Nginx
            filename = "%s_%s" % (store_fname.replace('/', '_').replace('\\', '_'), vals.get('name'))
            attachment_url = self._sync_image_to_nginx(file_data, filename)
            if attachment_url:
                attachment_id.write({'attachment_url': attachment_url})
        return res_ids

    def unlink(self):
        """删除时同步清理static文件"""
        for attach in self:
            if attach.attachment_url and os.path.exists(attach.attachment_url):
                try:
                    os.remove(attach.attachment_url)
                    # 尝试清理空目录
                    dir_path = os.path.dirname(attach.attachment_url)
                    if not os.listdir(dir_path):
                        os.rmdir(dir_path)
                    _logger.info(f"已删除: {attach.attachment_url}")
                except Exception as e:
                    _logger.error(f"删除失败: {str(e)}")
        return super().unlink()

    def write(self, vals):
        try:
            bin_data = base64.b64decode(vals.get('datas', '')) or False
        except binascii.Error:
            raise UserError(_("Attachment is not encoded in base64."))
        if self.mimetype and self.mimetype.startswith('image'):
            checksum = self._compute_checksum(bin_data)
            attachment_id = self.env['ir.attachment'].search([
                ('id', '!=', self.id),
                ('res_model', '=', 'ir.attachment'),
                ('checksum', '=', checksum),
            ])
            if attachment_id and attachment_id.attachment_url:
                vals['attachment_url'] = attachment_id.attachment_url
        return super(IrAttachment, self).write(vals)

在这里插入图片描述
在这里插入图片描述

2.3.静态文件的获取和显示

# -*- coding: utf-8 -*-
import json
import logging

from odoo.http import Controller, request, route


class ProductController(Controller):

    @route(['/api/product/list'], type='http', auth='public', methods=['GET', 'OPTIONS'], csrf=False, cors='*')
    def api_product_list(self, **kw):
        logging.info('api_product_list:%s', kw)
        product_ids = request.env['product.product'].sudo().search([])
        data = []
        for product_id in product_ids:
            domain = [
                ('res_model', '=', 'product.template'),
                ('res_field', '=', 'image_1920'),
                ('res_id', 'in', product_id.product_tmpl_id.id),
            ]
            attachment_id = request.env['ir.attachment'].sudo().search(domain)
            data.append({
                'id': product_id.id,
                'name': product_id.name,
                'lst_price': product_id.lst_price,
                'thumbnail': attachment_id.attachment_url
            })
        return json.dumps({'code': 200, 'data': data, 'count': len(product_ids)})

在这里插入图片描述
在这里插入图片描述

3.总结

nginx静态文件的方式可以扩展到系统日志、备份等需要保存文件的场景。


http://www.kler.cn/a/560012.html

相关文章:

  • 第二个接口-分页查询
  • 网站快速收录:如何优化网站图片Alt标签?
  • 如何安装vm和centos
  • 基于 IMX6ULL 的环境监测自主调控系统
  • github如何创建空文件夹
  • 图像处理篇---图像处理中常见参数
  • 基础学科与职业教育“101计划”:推动教育创新与人才培养
  • Windows逆向工程入门之逻辑运算指令解析与应用
  • 湖北中医药大学谱度众合(武汉)生命科技有限公司研究生工作站揭牌
  • 异常(1)
  • 如何在java中用httpclient实现rpc post 请求
  • linux-多进程基础(1) 程序、进程、多道程序、并发与并行、进程相关命令,fork
  • 瑞幸咖啡×动漫IP:精选联名案例,解锁品牌营销新玩法
  • Python生成器2-250224
  • unity学习52:UI的最基础组件 rect transform,锚点anchor,支点/轴心点 pivot
  • 如何生成traceid以及可视化展示
  • 蓝桥杯 3.搜索
  • Spring Core面试题
  • MySQL数据库连接池泄露导致MySQL Server超时关闭连接
  • 硬件加速与技术创新双轮驱动:DeepSeek和ChatGPT性能进阶的未来蓝图