【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 Truedef _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_urlexcept Exception as e:_logger.error(f"同步失败: {str(e)}")return False@api.model_create_multidef 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')):continuestore_fname = res_id.store_fnameattachment_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})continueif not res_id._is_image_mimetype():continueif not vals.get('res_id'):continueattachment_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# 同步到Nginxfilename = "%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_idsdef 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 Falseexcept 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_urlreturn super(IrAttachment, self).write(vals)

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

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

# -*- coding: utf-8 -*-
import json
import loggingfrom odoo.http import Controller, request, routeclass 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.rhkb.cn/news/23596.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek掘金——基于DeepSeek-R1构建文档问答机器人

DeepSeek掘金——基于DeepSeek-R1构建文档问答机器人 在这个项目中,我们将结合本地 AI 的隐私与 Deepseek R1 的智能,创建一个完全本地化、推理驱动的问答机器人。 在人工智能 (AI) 日益融入我们日常生活的时代,一个问题仍然处于最前沿:隐私。尽管基于云的 AI 系统功能强大…

计算机毕业设计Hadoop+Spark+DeepSeek-R1大模型民宿推荐系统 hive民宿可视化 民宿爬虫 大数据毕业设计(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

将maya模型物体材质转化为面材质

将maya模型物体材质转化为面材质&#xff0c;以在导出abc时继承材质信息&#xff1b; 运行一下python代码&#xff1a; import maya.cmds as cmds objListcmds.ls(slTrue) for obj in objList:shapeNodeNamecmds.listRelatives(obj, shapesTrue)sgNodesListcmds.listConnecti…

数据库面试题(基础常考!!!)

在数据库领域&#xff0c;无论是日常开发还是面试场景&#xff0c;都有一些高频且重要的问题需要我们深入理解和掌握。本文将对这些常见面试题进行详细阐述&#xff0c;帮助大家更好地应对面试和实际工作中的挑战。 面试题一&#xff1a;三范式详解 什么是三范式 三范式是关…

论文笔记(七十二)Reward Centering(三)

Reward Centering&#xff08;三&#xff09; 文章概括摘要3 基于值的奖励中心化4 案例研究&#xff1a; 以奖励为中心的 Q-learning5 讨论、局限性与未来工作致谢 文章概括 引用&#xff1a; article{naik2024reward,title{Reward Centering},author{Naik, Abhishek and Wan…

鸿蒙开发深入浅出01(基本环境搭建、页面模板与TabBar)

鸿蒙开发深入浅出01&#xff08;基本环境搭建、页面模板与TabBar&#xff09; 1、效果展示2、下载 DevEco Studio3、创建项目4、新建页面模板5、更改应用信息6、新建以下页面7、Index.ets8、真机运行9、图片资源文件 1、效果展示 2、下载 DevEco Studio 访问官网根据自己的版本…

蓝桥杯第十六届嵌入式模拟编程题解析

由硬件框图可以知道我们要配置LED 和按键 LED 先配置LED的八个引脚为GPIO_OutPut&#xff0c;锁存器PD2也是&#xff0c;然后都设置为起始高电平&#xff0c;生成代码时还要去解决引脚冲突问题 按键 按键配置&#xff0c;由原理图按键所对引脚要GPIO_Input 生成代码&#xf…

二叉树的遍历知识点及习题

一、知识点 1二叉树的遍历理解为按照预先定好的搜索路径访问树里的每个节点&#xff0c;且每个节点仅访问一次 2假设根节点为N&#xff0c;左子树为L&#xff0c;右子树为R&#xff0c;常见的三种遍历方法分别是先&#xff08;前&#xff09;序遍历NLR 根左右&#xff0c;中序…

“conda”不是内部或外部命令,也不是可运行的程序或批处理文件

有的时候&#xff0c;我们发现在cmd黑框中输入conda时&#xff0c;cmd会显示“conda”不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件&#xff0c;那这时候该怎么解决呢&#xff1f; Step01&#xff1a;我们找到Anconda的安装目录。然后找到里面的bin文件夹&am…

特辣的海藻!3

基础知识点 判断一个数是否是2的幂次 方法一&#xff1a;位运算 所有2的幂次数的二进制表示中有且仅有一个1&#xff0c;进行位运算 n&(n-1) 后结果为0 检查正数&#xff1a;n > 0&#xff08;负数和0不是2的幂次&#xff09;位运算&#xff1a; n & ( n -1) 会…

苍穹外卖中的模块总结

本文总结苍穹外卖项目中可复用的通用设计 sky-common constant存放常量类&#xff0c;包括消息常量&#xff0c;状态常量 context是上下文对象&#xff0c;封装了threadlocal package com.sky.context;public class BaseContext {public static ThreadLocal<Long> thre…

Threejs教程一【三要素】

场景 场景是一个容器&#xff0c;用于容纳所有的物体、光源、相机等元素。 // 创建场景 const scene new THREE.Scene(); //修改背景颜色&#xff0c;颜色支持十六进制、rgb、hsl、贴图等 scene.background new THREE.Color(0x000000);相机 相机决定了渲染的结果&#xff…

Deepseek和Grok 3对比:写一段冒泡排序

1、这是访问Grok 3得到的结果 2、grok3输出的完整代码&#xff1a; def bubble_sort(arr):n len(arr) # 获取数组长度# 外层循环控制排序轮数for i in range(n):# 内层循环比较相邻元素&#xff0c;j的范围逐渐减少for j in range(0, n - i - 1):# 如果当前元素大于下一个元…

TCP/UDP调试工具推荐:Socket通信图解教程

TCP/UDP调试工具推荐&#xff1a;Socket通信图解教程 一、引言二、串口调试流程三、下载链接 SocketTool 调试助手是一款旨在协助程序员和网络管理员进行TCP和UDP协议调试的网络通信工具。TCP作为一种面向连接、可靠的协议&#xff0c;具有诸如连接管理、数据分片与重组、流量和…

Open WebUI 是什么

Open WebUI 是什么 Open WebUI 是一个可扩展、功能丰富且用户友好的自托管 AI 平台,旨在完全离线运行。它支持各种 LLM 运行器,如 Ollama 和 OpenAI 兼容的 API,并内置了 RAG 推理引擎,使其成为强大的 AI 部署解决方案。 https://github.com/open-webui/open-webui 🚀 …

登录-05.JWT令牌-介绍

一.JWT令牌 JWT令牌是一种简洁的、自包含的格式&#xff0c;用于在通讯双方之间以json数据格式安全的传输数据。说白了&#xff0c;JWT令牌就是将json格式的数据进行封装&#xff0c;从而实现安全传输。 所谓简洁&#xff0c;就是指JWT令牌就是一个简单的字符串。 所谓自包含…

短剧小程序系统源码

短剧小程序系统源码 今天我要向大家介绍的是最新作品——短剧小程序系统源码。这不仅仅是一款简单的播放工具&#xff0c;它背后蕴含的强大功能能够帮助你的短剧业务实现质的飞跃&#xff01; 为什么说这款源码很厉害&#xff1f; 首先&#xff0c;在当今竞争激烈的市场环境…

【够用就好006】-PC桌面管理ECS服务器的实操步骤

背景介绍解决思路拓展知识 背景介绍 #够用就好#知其然知其所以然#aigc创意人左边 我计划搭建个人网站&#xff0c;计划格式化我的ECS服务器&#xff0c;但是里面有我之前的实践项目&#xff0c;我舍不得删除&#xff0c;我想要保存到本地。 通常我都是在vscode中用remotes ssh…

Ubuntu非conda环境python3.8下安装labelme

很久没用过labelme了&#xff0c;造实验数据需要在一个没有conda的Ubuntu20.04安装了python3.8.10的环境下安装labelme&#xff0c;先是直接执行 pip install labelme 执行了多次每次都是卡死&#xff0c;后来先执行pip install pyqt发现也是卡死在同样的地方&#xff0c;发现…

hi3516cv610修改i2c0引脚位置

hi3516cv610修改i2c引脚位置 我们i2c0位置改为 也就没用海思默认的Pin44 Pin43 Pin26、Pin65分别对应寄存器地址为 0x11130034_Pin26 0x17940004_Pin65 这里我们只需改 pin_mux.c文件 文件路径 ./smp/a7_linux/source/interdrv/sysconfig 改为这样ok pin_mux.c#include &quo…