• [互动交流] putObject上传图片返回成功,但是桶里面没有图片
    提示上传成功,但是桶里面没有文件result:上传文件返回结果​
  • [互动交流] obsutil目前只有64位工具可下载,是否有32位的工具
    在官网上可以下载到各操作系统64位的obsutil工具包,是否有32位的工具包可以下载,搜索开源的资料找不到。
  • [其他] 基于华为云智能声音识别的实践设计
    前言近年来,随着科技的发展,智能语音识别技术被广泛应用于人机交互领域。智能语音识别技术的出现让人们可以通过口头语言与计算机进行交互,极大地方便了人们的生活。借助Modelarts平台快速构建声音分类模型并部署上线,能够轻松实现智能声音识别。声音识别具有专属、方便、安全的优势。声音识别就是把acoustical signal转换成ELECTRICAL SIGNAL ,再用计算机进行识别。不同的任务和应用会使用不同的声音识别技术,如缩小刑侦范围时可能需要辨认技术,而银行交易时则需要确认技术。是生物识别技术的一种。本篇文章将介绍一种基于智能声音识别的实践设计,该设计利用基于华为云的智能声音识别技术,旨在提供一种新的人机交互方式,为人们的生活带来更加便捷的体验。设计背景采矿业、修建隧道时,及其容易发生塌方等意外,容易造成人员以及财产的损失,而实际上,在塌方出现前,地面会发出异常的震动声波。本文旨在以智能声音识别为主要技术,依托Modelarts 和OBS等技术设计一个声音探测预警装置。采矿业、修建隧道时,及其容易发生塌方等意外,容易造成人员以及财产的损失,而实际上,在塌方出现前,地面会发出异常的震动声波。本文旨在以智能声音识别为主要技术,依托Modelarts 和OBS等技术设计一个智能声音探测预警装置。实践设计原理智能声音识别的实践设计基于acoustical signal processing和machine learning technique。主要的步骤包括:音频采集和预处理、特征提取、模型训练和声音识别。1.音频采集和预处理:通过麦克风等设备采集用户的acoustical signal,并对acoustical signal进行预处理,包括降噪、滤波等操作,以提高acoustical signal的质量和可靠性。2.特征提取:将预处理后的acoustical signal转化为数字表示,即提取出语音的特征。常用的特征包括梅尔频谱系数(MFCC)、线性预测编码(LPC)等。3.模型训练:使用机器学习算法,如深度神经网络(DNN)、隐马尔科夫模型(HMM)等,对提取到的语音特征进行训练,建立声学模型。4.声音识别:将待识别的acoustical signal转化为特征表示,然后利用训练好的声学模型进行识别,得到最终的文本结果。应用技术及其优势智能声音识别主要用到的技术是Modelarts和OBS。其中Modelarts具有AI共享、快速有效管理、训练加速、自动学习的优势。其中的AI共享是指AI市场基于ModelArts构建的开发者生态社区所提供AI模型共享功能。为高校科研机构、AI应用开发商、解决方案集成商、企业及个人开发者等提供安全、开放的共享及交易环境,有效连接AI开发生态链各参与方。而OBS则时负责存储音频数据集和模型数据。主要功能实现1.声音检测可以通过对设备传来的声音进行分析,及时判断是否存在故障,并提前做出预警,防止设备出现重大故障或意外事故,保障矿山的生产安全或隧道建设人员的安全。2.声音检测可以对洞内环境中的噪音、震动等情况进行监测,帮助矿山管理部门及时发现并解决存在的环境问题以及预防意外,为人员的撤离提供充足的时间3.声音检测可以通过对设备运转时的声音进行分析,评估设备的能耗状况,帮助矿山管理部门或隧道的挖凿制定节能措施和优化设备运行策略,降低成本。此外,声音检测可以配合其他监测技术,进行对设备状态的全面监测,帮助相关管理部门了解设备的运行状态和健康状况,科学制定设备维护和保养计划。设计实现步骤1.资源准备:获取访问密钥(个人中心,管理我的凭证);2.准备数据:下载音频格式->转换音频格式->确认音频格式。具体步骤如下:将收集好的相关音频数据上传至平台,下载音频转换工具,转换音频文件格式为wav。3.创建项目:Modelarts 自动学习,选择声音自动学习项目。计费模式:按需计费。名称:sound-signal-of-mountain。数据集来源:新建数据集,数据集名称:sound-signal。数据集输入位置:/soundsignal/train/数据集输出位置:/soundsignal/out/(创建一个新的桶,并创建两个命名为train和out 的文件夹)。4.数据标注:在“自动学习”页面,单击项目名称,进入自动学习“数据标注”页面。声音分类项目创建时,音频来源有两种,选择本地添加。注意事项: 仅支持WAV格式音频文件,单个音频文件不能超过4MB,且单次上传的音频文件总大小不能超过8MB。 用于训练的音频,至少有2种以上的分类,每种分类的音频数不少于5个。5.自动训练:完成音频标注后,可进行模型的训练。由于用于训练的音频,至少有2种以上的分类,每种分类的音频数不少于5个。因此在发布训练之前,请确保已标注的音频符合要求,否则下方“开始训练”按钮会处于灰色状态。6.部署上线:部署上线操作即将模型部署为在线服务,并且提供在线的测试UI与监控能力。完成模型训练后,可选择准确率理想且训练状态为“运行成功”的版本部署上线。当“部署上线”页签版本管理区域的状态由“部署中”变更为“运行中”,部署完成。7.服务测试: 服务测试方式分为两种:在线页面测试:可以在“部署上线”页面,单击目标服务“操作”列的“预测”,进行服务测试。代码测试:可以通过调用代码对服务进行测试。代码测试方式有postman、curl命令等。8.相关资源的释放。9.设计相关电路,组装器件,编辑代码以实现预测报警等功能。总结这款基于华为云智能声音识别的智能声音探测预警装置是一种应用于采矿业、隧道开凿等地下工作场所的安全隐患解决方案。该设计利用到的技术有Modelarts 和OBS,利用了Modelarts 的AI共享和自动学习等优势。
  • [互动交流] 上传功能,跨域报错这个怎么处理?has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
    上传功能,跨域报错这个怎么处理?has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
  • [技术干货] 【FAQ】存储服务,9月问题总结,及知识点汇总
    常见问题及总结1、obs-c-sdk下载对象问题 cid:link_12、browserjs 看官方文档生成临时url访问, AK/SK也是硬编码,这还是会有安全问题,如何解决啊 cid:link_23、uniapp使用obs的教程有吗?怎么导入obs的sdk啊? cid:link_34、批量删除文件接口幂等吗? cid:link_45、看到EVS-共享磁盘挂载之后需要自行搭建文件或者集群系统,有这方面的教程吗? cid:link_56、【java-sdk】使用obs的并发分段上传比直接上传速度还慢 cid:link_67、用标准示例请求,结果返回 HTTP Code: 404; cid:link_7OBS知识点汇总1、搬迁本地数据至OBS 如何短时间、低成本、安全、高效的将本地数据搬迁至OBS?根据数据量、耗时、费用等需求,OBS提供了5种搬迁方式 cid:link_82、迁移其他云服务厂商数据至OBS 使用华为云OBS的海量存储能力,但数据在其他云厂商对象存储上,采用普通的下载上传方式费时费力,该怎么办 cid:link_83、使用备份软件实现本地数据备份至OBS 传统的备份方案存在系统复杂、投入成本高等诸多弊端,选择合适的备份软件,将本地数据备份至OBS,以降低成本,保障备份数据的安全。 cid:link_94、在ECS上通过内网访问OBS ECS默认通过公网方式访问OBS,公网方式响应速度会因为网络质量而受到影响,读取数据还将收取一定的流量费用。为最大化的优化性能、节省开支,您可以试着在ECS上通过内网访问OBS。 cid:link_105、使用自定义域名托管静态网站 OBS提供默认的托管静态网站域名,而自定义域名托管静态网站需要进行哪些操作? cid:link_116、通过CDN加速访问OBS 随着业务量增加,频繁的数据访问请求,影响OBS响应速度,同时会消耗大量的流量费用。通过CDN加速访问OBS可以降低成本,提供终端用户感受。 cid:link_117、企业数据权限控制 对于企业存储在OBS中的数据,部门公共数据权限应该如何管理?部门/项目之间如何共享数据?企业数据与合作伙伴数据如何隔离? cid:link_128、对象存储官方帮助文档 cid:link_0
  • [互动交流] obs-c-sdk下载对象问题
    实现了一个函数去下载3个不同的对象。为什么每次调用这个函数下载的第一个对象的速度要慢一些。更换下载顺序也是第一个要慢。obs_get_object took 0.215034 seconds. obs_get_object took 0.0211676 seconds. obs_get_object took 0.0365778 seconds. 
  • [技术干货] Redis在Java开发中的基本使用和巧妙用法【转】
    Redis是一款高性能的内存数据结构存储系统,能够支持多种数据结构类型,如字符串、哈希、列表、集合、有序集合等,也能够支持高级功能,如事务、发布/订阅、Lua脚本等,具有高可用性、高并发性和可扩展性的优点。Redis是一款高性能的内存数据结构存储系统,能够支持多种数据结构类型,如字符串、哈希、列表、集合、有序集合等,也能够支持高级功能,如事务、发布/订阅、Lua脚本等,具有高可用性、高并发性和可扩展性的优点。在Java开发中,Redis可以作为一个非常优秀的缓存和数据存储解决方案。本文将介绍Redis在Java开发中的巧妙用法。1 使用Jedis客户端库Jedis是Redis的Java客户端库,提供了方便的Java API,可以让我们在Java中使用Redis。Jedis提供了对所有Redis命令的支持,并且是线程安全的。在使用Jedis时,需要创建JedisPool对象来管理Jedis实例,以提高性能和效率。例如,以下代码演示如何使用Jedis实现一个字符串缓存:JedisPool jedisPool = new JedisPool("localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { String key = "name"; String value = jedis.get(key); if (value == null) { value = "Redis"; jedis.set(key, value); } System.out.println("Value for key " + key + " is " + value);}jedisPool.close();上面的代码创建了一个JedisPool对象,连接Redis服务器,然后使用Jedis实例获取缓存中的值,如果值不存在,则设置缓存值为“Redis”。2 Redis的数据结构Redis支持多种数据结构类型,如字符串、哈希、列表、集合、有序集合等。下面介绍如何在Java中使用这些数据结构类型。2.1 字符串类型Redis的字符串类型可以存储任意类型的数据,如数字、对象、JSON等。在Java中,我们可以将Java对象序列化为字符串,然后将其存储在Redis中。例如,以下代码演示如何使用Jedis实现一个简单的字符串缓存:JedisPool jedisPool = new JedisPool("localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { String key = "user:1:name"; User user = new User(1L, "John"); String value = jedis.get(key); if (value == null) { value = JSON.toJSONString(user); jedis.set(key, value); } User cachedUser = JSON.parseObject(value, User.class); System.out.println("Cached user is " + cachedUser.getName());}jedisPool.close();上面的代码创建了一个User对象,将其序列化为JSON字符串,然后使用Jedis实例将其存储在Redis中。如果缓存中不存在该值,则设置缓存值为User对象的JSON字符串。最后,我们从Redis中获取缓存值,并将其反序列化为User对象。2.2 哈希类型Redis的哈希类型可以存储多个键值对,类似于Java中的Map。在Java中,我们可以使用Java Map类型表示Redis哈希类型,并使用Jedis提供的API来操作哈希类型。例如,以下代码演示如何使用Jedis实现一个简单的哈希类型缓存:javaCopy codeJedisPool jedisPool = new JedisPool("localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { String key = "user:1"; Map fields = new HashMap<>(); fields.put("name", "John"); fields.put("age", "30"); fields.put("email", "john@example.com"); String result = jedis.hmset(key, fields); System.out.println("Result of hmset: " + result); String name = jedis.hget(key, "name"); System.out.println("Name: " + name); Map allFields = jedis.hgetAll(key); System.out.println("All fields: " + allFields);}jedisPool.close();上面的代码创建了一个Map对象,表示一个用户对象的属性。然后,使用Jedis的hmset方法将这些属性存储为哈希类型。最后,使用Jedis的hget和hgetAll方法来获取该用户对象的属性。2.3 列表类型Redis的列表类型是一个有序的列表,支持在列表的两端添加或删除元素。在Java中,我们可以使用Java List类型表示Redis列表类型,并使用Jedis提供的API来操作列表类型。例如,以下代码演示如何使用Jedis实现一个简单的列表类型缓存:javaCopy codeJedisPool jedisPool = new JedisPool("localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { String key = "tasks"; List tasks = new ArrayList<>(); tasks.add("Task 1"); tasks.add("Task 2"); tasks.add("Task 3"); long result = jedis.lpush(key, tasks.toArray(new String[0])); System.out.println("Result of lpush: " + result); String task = jedis.rpop(key); System.out.println("Task: " + task); List allTasks = jedis.lrange(key, 0, -1); System.out.println("All tasks: " + allTasks);}jedisPool.close();上面的代码创建了一个List对象,表示任务列表。然后,使用Jedis的lpush方法将这些任务存储为列表类型。最后,使用Jedis的rpop和lrange方法来获取该任务列表的任务。2.4 集合类型Redis的集合类型是一个无序的集合,支持添加、删除和查询元素。在Java中,我们可以使用Java Set类型表示Redis集合类型,并使用Jedis提供的API来操作集合类型。例如,以下代码演示如何使用Jedis实现一个简单的集合类型缓存:JedisPool jedisPool = new JedisPool("localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { String key = "tags"; Set tags = new HashSet<>(); tags.add("Java"); tags.add("Redis"); tags.add("Database"); long result = jedis.sadd(key, tags.toArray(new String[0])); System.out.println("Result of sadd: " + result); boolean exists = jedis判断元素是否存在于该集合中:boolean exists = jedis.sismember(key, "Java");System.out.println("Exists: " + exists);Set allTags = jedis.smembers(key);System.out.println("All tags: " + allTags);}jedisPool.close();上面的代码创建了一个Set对象,表示标签集合。然后,使用Jedis的sadd方法将这些标签存储为集合类型。最后,使用Jedis的sismember和smembers方法来判断元素是否存在于该集合中和获取该集合的所有元素。3 高级用法除了上述基本的Redis数据类型和Jedis API用法之外,还有一些高级用法可以提高Redis缓存的效率和可靠性。3.1 连接池在Java应用程序中使用Jedis连接Redis服务器时,每个线程都需要创建和销毁连接,这会造成大量的性能开销。为了减少这种开销,可以使用Jedis连接池来管理连接,使连接在需要时从连接池中获取,使用完毕后归还到连接池中。以下代码演示如何使用Jedis连接池:edisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(10);JedisPool jedisPool = new JedisPool(poolConfig, "localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { // 使用Jedis操作Redis服务器}jedisPool.close();上面的代码创建了一个Jedis连接池,并设置最大连接数为10。在使用Jedis连接Redis服务器时,可以通过jedisPool.getResource()方法从连接池中获取连接。3.2 事务Redis支持事务,可以将一系列操作作为一个原子性操作执行。在Java中,我们可以使用Jedis提供的Transaction类来执行Redis事务。以下代码演示如何使用Jedis实现一个简单的Redis事务:javaCopy codeJedisPool jedisPool = new JedisPool("localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { Transaction transaction = jedis.multi(); transaction.set("key1", "value1"); transaction.set("key2", "value2"); transaction.set("key3", "value3"); List<cke:object> result = transaction.exec(); System.out.println("Result of transaction: " + result);}jedisPool.close();</cke:object>上面的代码使用Jedis创建了一个Transaction对象,并将一系列操作添加到该事务中。最后,通过Transaction对象的exec方法执行该事务。3.3 发布/订阅Redis支持发布/订阅模式,可以将消息发布到指定的频道,并由订阅者接收该频道的消息。在Java中,我们可以使用Jedis提供的PubSub类来实现Redis发布/订阅模式。以下代码演示如何使用Jedis实现Redis发布/订阅模式:javaCopy codeJedisPool jedisPool = new JedisPool("localhost", 6379);try (Jedis jedis = jedisPool.getResource()) { JedisPubSub jedisPubSub = new PubSub() {@Overridepublic void onMessage(String channel, String message) {System.out.println("Message received. Channel: " + channel + ", Message: " + message);} @Override public void onSubscribe(String channel, int subscribedChannels) { System.out.println("Subscribed to channel: " + channel); } @Override public void onUnsubscribe(String channel, int subscribedChannels) { System.out.println("Unsubscribed from channel: " + channel); }};jedis.subscribe(jedisPubSub, "channel1"); }jedisPool.close();上面的代码使用Jedis创建了一个PubSub对象,并实现了其onMessage、onSubscribe和onUnsubscribe方法。最后,通过jedis.subscribe方法订阅指定的频道,并接收该频道的消息。4. 结论本文介绍了Redis的Java巧妙用法,涉及了基本的Redis数据类型、Jedis API的基本用法,以及高级用法如连接池、事务和发布/订阅模式等。这些巧妙用法可以帮助Java开发人员更好地使用Redis实现高效、可靠的缓存。除了在Java中使用Jedis操作Redis,还可以使用Spring Data Redis,这是一个基于Spring框架的Redis客户端,提供了更加简洁易用的API,并且与Spring框架集成得更好。Spring Data Redis提供了以下核心组件:RedisTemplate:一个通用的Redis操作模板类,封装了Jedis的所有操作,包括基本数据类型、高级数据类型、事务、Pipeline、Lua脚本等。RedisRepository:一个基于RedisTemplate的通用数据访问接口,提供了CRUD操作和查询功能,类似于JPA的Repository。RedisCacheManager:一个基于Redis的缓存管理器,提供了缓存的读取、写入、删除等操作。以下是一个使用Spring Data Redis的示例代码:javaCopy code@Configuration@EnableCachingpublic class RedisConfig extends CachingConfigurerSupport { @Bean public RedisConnectionFactory redisConnectionFactory() { return new JedisConnectionFactory(); } @Bean public RedisTemplate redisTemplate() { RedisTemplate redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory()); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return redisTemplate; } @Bean public CacheManager cacheManager() { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate()); cacheManager.setDefaultExpiration(300); return cacheManager; }}上面的代码使用Spring注解方式配置Redis连接和缓存管理器。其中,RedisTemplate使用了Jackson序列化和反序列化JSON对象,缓存管理器默认缓存时间为300秒。以下是一个使用Spring Data Redis的数据访问示例代码:javaCopy code@Repositorypublic class UserRepositoryImpl implements UserRepository { @Autowired private RedisTemplate redisTemplate; private static final String KEY = "user:%s"; @Override public User save(User user) { String key = String.format(KEY, user.getId()); redisTemplate.opsForValue().set(key, user); return user; } @Override public User findById(String id) { String key = String.format(KEY, id); return redisTemplate.opsForValue().get(key); }}上面的代码使用了Spring注解方式注入RedisTemplate,实现了UserRepository接口,使用RedisTemplate的opsForValue方法实现了save和findById方法。Spring Data Redis提供了更加简洁易用的API,同时也集成了Spring框架,与其他Spring组件无缝衔接,使得在Spring应用程序中使用Redis变得更加容易。5 总结本文介绍了Redis在Java中的巧妙用法,包括基本数据类型和Jedis API的基本用法,以及高级用法如连接池、事务和发布/订阅模式等。同时,还介绍了使用Spring Data Redis的方法,使得在Spring应用程序中使用Redis变得更加容易。这些方法可以帮助Java开发人员更好地使用Redis实现高效、可靠的缓存。6 结语Redis作为一款高性能、高可靠的缓存和数据存储工具,被广泛应用于互联网和大数据领域。本文介绍了Redis在Java中的巧妙用法,包括基本数据类型和Jedis API的基本用法,以及高级用法如连接池、事务和发布/订阅模式等。同时,还介绍了使用Spring Data Redis的方法,使得在Spring应用程序中使用Redis变得更加容易。这些方法可以帮助Java开发人员更好地使用Redis实现高效、可靠的缓存。原文链接:https://www.51cto.com/article/747333.html
  • [技术干货] Glide缓存机制【转】
    内存缓存/运行时缓存分为两部分:活动缓存(ActiveResource)和Lru内存缓存(LruResourceCache)。缓存机制简介1、缓存的图片资源原始图片(Source) :即图片源的图片初始大小和分辨率;转换后的图片(Result) :经过尺寸缩放和大小压缩等处理后的图片;当使用Glide加载图片时,Glide会默认根据View视图对图片进行压缩和转换,而不显示原始图。(这也是Glide加载速度高于Picasso的原因)2、缓存机制设计Glide的缓存功能设计成二级缓存:内存缓存和硬盘缓存。(从网络加载不属于缓存)内存缓存:防止重复将图片读入到内存,造成内存资源浪费,只缓存转换后的图片,而不是原始图片;磁盘缓存:防止重复从网络或其他地方下载和读取数据,可缓存原始图片和转换过后的图片,用户自行设置;在Glide中,缓存的读取顺序为:内存缓存 –> 磁盘缓存 –> 网络 ,内存缓存和磁盘缓存相互不影响,独立配置,内存缓存是默认开启的。Glide的缓存机制使得Glide具备非常好的图片缓存效果,从而使得具备较高的图片加载效率。以下是Glide的相关代码:// 默认开启内存缓存,用户不需要作任何设置Glide.with(this).load(url).into(imageView);// 可通过API禁用内存缓存功能Glide.with(this).load(url).skipMemoryCache(true) // 禁用内存缓存 .into(imageView);Glide.with(this).load(url) .diskCacheStrategy(DiskCacheStrategy.NONE) // 不缓存任何图片,即禁用磁盘缓存 .into(imageView);// DiskCacheStrategy.NONE:不缓存任何图片,即禁用磁盘缓存// DiskCacheStrategy.ALL :缓存原始图片 & 转换后的图片// DiskCacheStrategy.SOURCE:只缓存原始图片(原来的全分辨率的图像,即不缓存转换后的图片)// DiskCacheStrategy.RESULT:(默认)只缓存转换后的图片(即最终的图像:降低分辨率后 / 或者转换后 ,不缓存原始图片3、 缓存类型活动缓存(ActiveResource):存储正在使用的图片;Lru内存缓存(LruResourceCache):图片解析完成后并最近被加载过会放到内存中;磁盘缓存-资源类型(DiskCache - Resource):被解码后的图片写入磁盘文件中;磁盘缓存-原始数据(DiskCache - Data):网络请求成功或在本地获取成功后,将原始数据在磁盘中缓存;Lru(Least Recently Used):最近最少使用,它的核心思想是,当缓存满的时候,会优先淘汰最近最少使用的缓存对象。4、内存缓存/运行时缓存内存缓存/运行时缓存分为两部分:活动缓存(ActiveResource)和Lru内存缓存(LruResourceCache)。LinkedHashMap继承自HashMap,在此基础上增加了双向链表的结构,每次访问数据的时候,会更新被访问的数据的链表指针。比如说从链表中删除并不是真正的删除数据,只是移动了链表的指针。Lru内存缓存:使用LinkedHashMap来缓存资源(强引用),并设定一个缓存的大小。如果有资源被访问到,首先会在链表中删除该节点,然后再添加到链表头,这样就可以保证链表头部的节点是最近访问过的。而当缓存的数量达最大值的时候,就会将链表尾部(最近最少使用)的数据移除。但是这样做有一个风险,就是容易将正在使用的资源回收掉。Glide这样设计:从内存缓存(LruResourceCache)中拿到资源时候就主动添加到活动缓存(ActiveResource)中,并清理Lru内存缓存(LruResourceCache)中的资源,这样做的好处就是是保护正在使用资源不被Lru算法回收掉。ActiveResources是一个弱引用的HashMap,用来缓存正在使用的图片,保存这个图片不会被Lru算法回收掉。图片用完之后会重新添加到Lru内存缓存中。ActiveResources和LruResourceCache是内存缓存,属于运行时缓存且互斥(同一张图片不会同时缓存在ActiveResources和LruResourceCache中),应用被杀死后内存缓存将不存在。5、 磁盘缓存磁盘缓存策略:DiskCacheStrategy.NONE:表示不缓存任何内容;DiskCacheStrategy.RESOURCE:在资源解码后将数据写入磁盘缓存,即经过缩放等转换后的图片资源;DiskCacheStrategy.DATA:在资源解码前将原始数据写入磁盘缓存;DiskCacheStrategy.ALL :使用DATA和RESOURCE缓存数据;DiskCacheStrategy.AUTOMATIC:它会尝试对本地和远程图片使用最佳的策略。当加载远程数据时,AUTOMATIC 策略仅会存储未被加载过程修改过的原始数据,因为下载远程数据相比调整磁盘上已经存在的数据要昂贵得多。对于本地数据,AUTOMATIC 策略则会仅存储变换过的缩略图,因为即使需要再次生成另一个尺寸或类型的图片,取回原始数据也很容易。默认使用这种缓存策略;在使用Glide去加载一张图片的时候,Glide默认不会将原始图片展示出来,而是会对图片进行压缩和转换。我们既可以缓存转换过的图片,也可以缓存转换之前的原始图片。采用LRU算法的缓存有两种:LruCache和DisLruCache,分别用于实现内粗缓存和硬盘缓存原文链接:https://www.51cto.com/article/747365.html
  • [技术干货] NFS文件系统中的RPC协议详解【转】
    正是由于在RPC数据包中包含的这些关键信息,当主机端发送的消息被服务端接收后,服务端根据这些信息就能知道应该调用哪个存根函数。前文我们介绍了NFS的整体架构,其核心是将主机端的函数调用通过网络传输到服务端,并转化为服务端的函数调用。其主要实现是主机端与服务端的一一对应的存根。那么这种转化是如何进行的呢?这就涉及到RPC协议了。在Linux NFS中,将网络文件系统分为两层,其中RPC协议承载了NFS协议。由于RPC协议的存在,是的NFS协议变得非常简单。RPC协议的全称为Remote Procedure Call,翻译成中文是远程过程调用。也就是通过该协议,可以实现一个远程的函数调用,这样在客户端调用一个函数,可以在服务端完成业务处理。而对于客户端来说并不关心该函数是在客户端还是服务端。这里的函数是经过特殊方式实现的,在NFS中称为存根(stub)。以Linux内核中的实现为例,文件系统的所有操作都对应着一个存根函数,具体如下所示。而客户端的这些存根函数在服务端也是有一一对应的存根函数的。Linux NFS中服务端的存根函数如下所示。所以,当客户端文件系统希望完成某一个文件操作时,比如创建子目录。那么在文件系统层面可以直接调用客户端的存根函数,比如nfs3_proc_mkdir。而该函数会将请求封装后通过RPC发送到服务端,服务端的程序会根据解析后的消息调用服务端对应的存根函数完成客户端期望的操作,然后给客户端反馈。那么这个流程是如何实现的呢?这就涉及到RPC协议的内容了。RPC的原理其实非常简单,如下是RPC数据包的格式,可以看出该格式中包含很多字段。这些字段就是用来描述存根函数的。Sun的RPC协议在设计的时候期望实现对多种服务的支持,比如NFS协议、挂载协议和NLM等。因此在设计RPC协议的时候,RPC有3个相关的字段来进行标识,其中Program字段标识程序,区分NFS、MOUNT和NLM等其它程序类型;Program Version字段标识程序版本,考虑升级的兼容性;Procedure字段则标识程序中的过程(函数),也就是存根函数。通过上述Program和Procedure等关键信息,当服务端收到该消息时就可以知道应该由哪个版本的哪个程序来处理该消息,而且进一步知道应该调用哪个存根函数(函数指针)来进行处理。上面的介绍更多的是理论层面的,我们通过WireShark抓个包看看Sun RPC是如何传输数据的,以及数据的格式。如图5‑8所示是我们抓取的挂载命令的数据包,我们可以对比一下该数据包的内容与协议的关系。可以看到,这里Program是100005;Program版本是3,也就是NFS v3的数据;Procedure的值为1。由于WireShark是支持RPC和NFS协议的,因此在图5‑8中上半部分可以看到具体的描述信息。在该图的下半部分则是原始的数据包数据。正是由于在RPC数据包中包含的这些关键信息,当主机端发送的消息被服务端接收后,服务端根据这些信息就能知道应该调用哪个存根函数。原文链接 https://www.51cto.com/article/762669.html
  • [存储类] Obs 断点续传不起作用,每次都重新上传
    @try {  if (self.currentTask != nil) {      [self.currentTask cancel];  }  self.config = config;  NSString * endPoint = [self.config objectForKey:@"endPoint"];  NSString * AK = [self.config objectForKey:@"accessKey"];  NSString * SK = [self.config objectForKey:@"secretKey"];  NSString * ST = [self.config objectForKey:@"securityToken"];  NSString * objectKey = [self.config objectForKey:@"objectKey"];  NSString * bucket = [self.config objectForKey:@"bucket"];    // 初始化身份验证  OBSStaticCredentialProvider *credentialProvider = [[OBSStaticCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];    //      OBSSTSCredentialProvider *credentialProvider = [[OBSSTSCredentialProvider alloc] initWithAccessKey:AK secretKey:SK];  credentialProvider.securityToken = ST;    //初始化服务配置  OBSServiceConfiguration *conf = [[OBSServiceConfiguration alloc] initWithURLString:[NSString stringWithFormat:@"https://%@",endPoint] credentialProvider:credentialProvider];      // 初始化client  OBSClient * client = [[OBSClient alloc] initWithConfiguration:conf];  _obsClient = client;  #if DEBUG    // *****日志设置*******    // 设置系统日志打印  [client addLogger:[OBSDDASLLogger sharedInstance]];    // 打开窗口打印  [client addLogger:[OBSDDTTYLogger sharedInstance]];    // 设置日志文件记录  OBSDDFileLogger *fileLogger = [[OBSDDFileLogger alloc] init];    // 保留时间  fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling                                              // 最大文件数目  fileLogger.logFileManager.maximumNumberOfLogFiles = 7;    // 自定义日志添加  [client addLogger:fileLogger];    // 日志文件地址  OBSDDLogFileInfo *ts =[fileLogger currentLogFileInfo];  NSLog(@"%@", ts);  //     设置日志等级  [client setLogLevel:OBSDDLogLevelDebug];  //     开启日志  [client setASLogOn];#endif    // 分段上传的最大并发数  client.configuration.maxConcurrentUploadRequestCount = 3;    // 分段上传请求的最大连接数  client.configuration.uploadSessionConfiguration.HTTPMaximumConnectionsPerHost = 5;  filePath = [filePath stringByReplacingOccurrencesOfString:@"file://"                                                 withString:@""];    // 填写Bucket名称,例如examplebucket。    // 填写文件完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。  NSString * contentMd5 = [self.class base64Md5ForFilePath:filePath];      if (contentMd5 == nil) {    @throw [NSException exceptionWithName:OBSBFTaskErrorDomain                                   reason:@"not found file"                                 userInfo:nil];  }    // 获取对象属性  OBSGetObjectMetaDataRequest *metaDataRequest = [[OBSGetObjectMetaDataRequest alloc] initWithBucketName:bucket objectKey:objectKey];  __block BOOL hasUpload = NO;  OBSBFTask *metaDataTask = [client getObjectMetaData:metaDataRequest completionHandler:^(OBSGetObjectMetaDataResponse *response, NSError *error){    NSLog(@"meta:%@\n storageClass:%@\n websiteRedirectlocation:%@\n size:%@", response.metaDataDict, @(response.storageClass), response.websiteRedirectLocation, response.size);    NSString * md5 = [response.metaDataDict valueForKey:@"contentmd5"];    if (md5 == nil) {      md5 = [response.metaDataDict valueForKey:@"contentMd5"];    }    if (md5 != nil && [md5 isEqualToString:contentMd5]) {      [self sendEventWithName:@"obsUploadProgress" body:@{        @"type" : @"onProgress",        @"currentSize" : [NSString stringWithFormat:@"%@", response.size],        @"totalSize" : [NSString stringWithFormat:@"%@", response.size],        @"md5" : contentMd5,        @"objectKey" : objectKey,        @"transferPercentage" : @"100"      }];      hasUpload = YES;      return;    }  }];  [metaDataTask waitUntilFinished];  if (hasUpload) {    if (resolve) {      resolve(@{ @"filePath" : filePath,                 @"md5" : contentMd5,                 @"objectKey" : objectKey              });    }    NSLog(@"文件已经存在,无需上传,直接成功 ! %@, %@", objectKey, filePath);    return;  }    OBSUploadFileRequest *request = [[OBSUploadFileRequest alloc]initWithBucketName:bucket objectKey:objectKey uploadFilePath:filePath];    // 分段大小为5MB  request.partSize = [NSNumber numberWithInteger: 5 * 1024*1024];    //      // 开启断点续传模式  request.enableCheckpoint = YES;    //      // 指定checkpoint文件路径  request.checkpointFilePath = [filePath stringByAppendingString:@".obsuploadcheckpoint.txt"];  request.enableMD5Check = YES;//  if ([[NSFileManager defaultManager] fileExistsAtPath:request.checkpointFilePath]) {//    //获取JSON文件的路径//      //将JSON文件转换成NSData对象//    NSData *data = [[NSData alloc] initWithContentsOfFile:request.checkpointFilePath];//      //将NSData对象转换成JSON对象//    NSError *error = nil;//    NSDictionary* jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];//      //检查转换是否成功//    if (error != nil) {//      NSLog(@"解析JSON失败:%@",error);//    } else {//        //解析JSON成功//     NSString * requestID = [jsonObject valueForKey:@"requestID"];//      NSString * uploadID = [jsonObject valueForKey:@"uploadID"];////      NSString * uploadFilePath = [jsonObject valueForKey:@"uploadFilePath"];//      request.requestID = requestID;////      request.lastUploadFilePath = uploadFilePath;//      NSLog(@"checkpoint requestID:%@,uploadID:%@",requestID, uploadID);////      self.upload2(jsonObject);//    }//  }  NSMutableDictionary * metaDataDict = [NSMutableDictionary dictionaryWithDictionary:request.metaDataDict];  [metaDataDict setObject:contentMd5 forKey:@"contentMd5"];//  [metaDataDict setObject:@{ @"md5": contentMd5 } forKey:@"userMetadata"];  [request setMetaDataDict:metaDataDict];      // 上传文件  request.uploadProgressBlock =  ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {    if (totalBytesExpectedToSend < 1) {      return;    }    NSLog(@"%0.1f%%",(float)floor(totalBytesSent*10000/totalBytesExpectedToSend)/100);    NSLog(@"%lld, %lld, %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);    if (!self.hasListeners) {      return;    }    [self sendEventWithName:@"obsUploadProgress" body:@{      @"type" : @"onProgress",      @"currentSize" : [NSString stringWithFormat:@"%lld", totalBytesSent],      @"totalSize" : [NSString stringWithFormat:@"%lld", totalBytesExpectedToSend],      @"md5" : contentMd5,      @"objectKey" : objectKey,      @"transferPercentage" : [NSString stringWithFormat: @"%0.0f",(float)floor(totalBytesSent*10000/totalBytesExpectedToSend)/100]    }];  };  self.currentTask = request;    OBSBFTask  *task = [client uploadFile:request completionHandler:^(OBSUploadFileResponse *response, NSError *error) {    NSLog(@"%@",response);    self.currentTask = nil;    if(error){        // 打印错误信息      NSLog(@"文件上传失败");      NSLog(@"%@",error);      if (reject) {        reject(@"-1", @"上传失败", error);      }      return;    }      // 上传文件成功,返回200,打印返回响应值    if([response.statusCode isEqualToString:@"200"]){      NSLog(@"文件上传成功");      NSLog(@"%@",response);      NSLog(@"%@",response.etag);      if (resolve) {        resolve(@{ @"filePath" : filePath,                   @"md5" : contentMd5,                   @"objectKey" : objectKey                });      }      NSLog(@"upload object success! %@, %@", objectKey, filePath);    } else {      NSLog(@"文件上传失败");      if (reject) {        reject(@"-1", @"上传失败", nil);      }    }  }];    [task waitUntilFinished];} @catch(NSException *e) {  self.currentTask = nil;  NSLog(@"obs upload error: %@", e);  NSError *error = [NSError errorWithDomain:OBSBFTaskErrorDomain                                       code:kOBSBFMultipleErrorsError                                   userInfo:@{ @"errors": e }];  reject(@"-1", e.reason, error);}
  • [互动交流] browserjs 看官方文档生成临时url访问, AK/SK也是硬编码,这还是会有安全问题,如何解决啊
    browserjs 看官方文档生成临时url访问, AK/SK也是硬编码,这还是会有安全问题,如何解决啊
  • [互动交流] uniapp使用obs的教程有吗?怎么导入obs的sdk啊?
    import ObsClient from "../../node_modules/esdk-obs-browserjs/dist/esdk-obs-browserjs-without-polyfill.3.23.5.min.js"; 这样子也不可以            let obsClient = new ObsClient({                         access_key_id: this.obsObj.access_key_id,                         secret_access_key: this.obsObj.secret_access_key,                         server: this.obsObj.server                     });
  • [介绍/入门] 使用FG服务打包函数依赖
    1、使用附件 index 文件在FunctionGraph服务中创建函数(创建时需要把rar压缩包转为zip压缩包),创建函数请参考 cid:link_0 ;2、修改requirements.txt文件的内容,把里面的内容替换成需要打包的依赖,多个依赖换行隔开;3、在index.py文件内,参考注释内容修改红框内的代码。部署执行代码后,会自动把requirements.txt内的所有依赖打包成一个文件并保存到OBS桶内,保存的文件名和桶的地址由index.py文件中红框内代码决定
  • [互动交流] 批量删除文件接口幂等吗?
    第一次1000个删除成功了990个,重试时依旧传递1000个key,重试时会因为已删除的990个导致本次删除失败吗?
  • [互动交流] 【java-sdk】使用obs的并发分段上传比直接上传速度还慢
    您好,我在使用OBS javasdk的文件上传API,使用中,我发现,对于大文件,使用官方提供的并发上传文件示例,比直接调 putObject方法速度还慢,具体代码如下:1.并发分段上传代码官方示例https://support.huaweicloud.com/sdk-java-devg-obs/obs_21_0607.html2.调用 putObject 上传文件public SaveObjectResult saveObject(String bucket, String objectKey, MultipartFile file) throws Exception { // 校验桶名称是否正确 bucket = checkBucketName(bucket); InputStream in = file.getInputStream(); SaveObjectResult saveObjectResult = new SaveObjectResult(); saveObjectResult.setOk(Boolean.FALSE); saveObjectResult.setStorageMediaType(OSSTypeEnum.OBS.name()); PutObjectResult putObjectResult = getClient().putObject(bucket, objectKey, in); if (putObjectResult != null && putObjectResult.getStatusCode() == HttpStatus.HTTP_OK) { saveObjectResult.setOk(Boolean.TRUE); saveObjectResult.setAccessUrl(putObjectResult.getObjectUrl()); } return saveObjectResult; }此处直接使用ObsCLient 的 PutObjectResult putObject(String bucketName, String objectKey, InputStream input) 方法。测试结果发现,使用并发分段上传,并没有节省时间,反而比直接使用putObject还慢,为什么会这样?怎么优化,才能让上传更快?
总条数:1601 到第 页
上滑加载中