You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

持久化模型视图截图后刷新页面图片失效问题求助

解决模型截图刷新后损坏的问题

这个问题我之前也碰到过,核心原因是你直接存储了浏览器生成的Blob URL——这种URL是浏览器内存里的临时引用,一旦页面刷新或者会话结束,这个引用就会失效,自然渲染不出图片了。

问题根源

viewer.getScreenShot返回的Blob URL(比如blob:http://xxx/xxxx-xxxx)并不是真正的图片数据,它只是浏览器为当前内存中的Blob对象创建的临时访问地址。当页面刷新时,浏览器会清理这些临时Blob资源,对应的URL也就无效了,所以你看到的是损坏的图片。

正确的解决方案

你需要把截图的实际图片数据(而不是临时URL)存储到数据库,后续渲染时再用这些数据生成可访问的图片源。这里推荐两种常用方式:

1. 存储Base64编码的图片数据

捕获截图后,把Blob转成Base64字符串,存储这个字符串到数据库。渲染时直接把Base64作为<img>src属性即可。

示例代码:

// 捕获截图并转成Base64
viewer.getScreenShot(1920, 1080, function(blobUrl) {
  fetch(blobUrl)
    .then(response => response.blob())
    .then(blob => {
      const reader = new FileReader();
      reader.onload = function(e) {
        // e.target.result 就是Base64格式的图片数据(格式:data:image/png;base64,xxxx...)
        const base64Screenshot = e.target.result;
        // 把base64Screenshot保存到数据库
        saveToDatabase(base64Screenshot);
      };
      reader.readAsDataURL(blob);
      // 记得释放临时的Blob URL,避免内存泄漏
      URL.revokeObjectURL(blobUrl);
    });
});

// 渲染时从数据库取出Base64,直接赋值给img的src
function renderScreenshot(base64Data) {
  const img = document.createElement('img');
  img.src = base64Data;
  document.body.appendChild(img);
}

2. 存储二进制图片数据

如果觉得Base64体积偏大(比原二进制大30%左右),可以直接存储Blob的二进制数据到数据库。渲染时再把二进制数据转成Blob并生成新的Blob URL。

示例代码:

// 捕获截图并转成二进制数据
viewer.getScreenShot(1920, 1080, function(blobUrl) {
  fetch(blobUrl)
    .then(response => response.arrayBuffer())
    .then(arrayBuffer => {
      // arrayBuffer就是二进制数据,可以直接存储到支持二进制字段的数据库(比如PostgreSQL的bytea,MongoDB的BinData)
      saveBinaryToDatabase(arrayBuffer);
      URL.revokeObjectURL(blobUrl);
    });
});

// 渲染时从数据库取出二进制数据,生成Blob URL
function renderBinaryScreenshot(binaryData) {
  const blob = new Blob([binaryData], { type: 'image/png' });
  const newBlobUrl = URL.createObjectURL(blob);
  const img = document.createElement('img');
  img.src = newBlobUrl;
  document.body.appendChild(img);
  
  // 页面卸载时记得释放URL,避免内存泄漏
  window.addEventListener('beforeunload', () => {
    URL.revokeObjectURL(newBlobUrl);
  });
}

注意事项

  • 不管用哪种方式,都要记得调用URL.revokeObjectURL()释放临时的Blob URL,避免浏览器内存泄漏。
  • 如果你的数据库支持二进制字段,优先用二进制存储,比Base64更节省空间。

内容的提问来源于stack exchange,提问作者sushilprj

火山引擎 最新活动