You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Deno Oak中显示Blob图片报错:Not allowed to load local resource

错误原因与解决方案

错误根源

你在后端(Deno Oak)调用的URL.createObjectURL是服务器端运行时的API,生成的Blob URL格式类似blob:file:///xxxxxx,仅在服务器进程内部有效。浏览器会将其识别为服务器本地资源,出于同源策略和安全限制,禁止前端加载这类跨上下文的资源,因此抛出「Not allowed to load local resource」错误。

注意:浏览器端的URL.createObjectURL才是生成浏览器可识别的临时Blob URL的正确方式,两者运行在完全不同的上下文,不能混用。


临时解决:上传后直接显示图片

若仅需实现上传后即时显示,可修改后端将图片转为Base64编码返回给前端:

后端修改代码

const uploadFiles = async(ctx:any)=>{
    const body = await ctx.request.body({type: 'form-data'});
    const product = await body.value.read({maxSize: 500000000 });
    if(!ctx.request.hasBody){
        ctx.response.status = 400;
        ctx.response.body ={
            success: false,
            msg: 'No data'
        }
    }else{
        try {
            const file = product.files[0].content;
            // 将二进制文件转为Base64编码
            const base64 = btoa(new Uint8Array(file).reduce((data, byte) => data + String.fromCharCode(byte), ''));
            const imgUrl = `data:image/jpeg;base64,${base64}`;
            
            ctx.render('./fu.ejs',{upload:true, urlData: imgUrl}); 
        } catch (err) {
            ctx.response.status = 200;
            ctx.response.body = {
                success: false,
                msg: err.toString()
           }
        }
    }
}

前端无需修改,直接使用返回的urlData作为img.src即可,Data URI是浏览器可直接识别的资源格式。


完整流程:存入数据库+读取显示

1. 上传时将图片存入数据库

推荐在数据库中存储图片的二进制数据(Blob类型字段,比Base64更节省空间),示例伪代码:

const uploadFiles = async(ctx:any)=>{
    const body = await ctx.request.body({type: 'form-data'});
    const product = await body.value.read({maxSize: 500000000 });
    if(!ctx.request.hasBody){
        ctx.response.status = 400;
        ctx.response.body ={
            success: false,
            msg: 'No data'
        }
    }else{
        try {
            const file = product.files[0].content;
            const mimeType = product.files[0].type || 'image/jpeg';
            
            // 将二进制数据存入数据库(以PostgreSQL为例)
            await db.query(`INSERT INTO images (data, mime_type) VALUES ($1, $2)`, [file, mimeType]);
            const imageId = // 获取刚插入的图片ID
            
            ctx.render('./fu.ejs',{upload:true, imageId: imageId}); 
        } catch (err) {
            ctx.response.status = 200;
            ctx.response.body = {
                success: false,
                msg: err.toString()
           }
        }
    }
}

2. 新增图片读取接口

后端注册接口,根据图片ID从数据库取出二进制数据并返回:

const getImage = async(ctx:any)=>{
    const imageId = ctx.params.id;
    // 从数据库查询图片数据与MIME类型
    const result = await db.query(`SELECT data, mime_type FROM images WHERE id = $1`, [imageId]);
    if(!result.rows.length){
        ctx.response.status = 404;
        ctx.response.body = 'Image not found';
        return;
    }
    const { data, mime_type } = result.rows[0];
    // 设置响应头
    ctx.response.headers.set('Content-Type', mime_type);
    // 返回二进制图片数据
    ctx.response.body = data;
}

// 路由注册示例
router.get('/images/:id', getImage);

3. 前端读取显示

前端直接使用接口地址作为图片源:

const etat = $('#etat').html();
const photoDiv = $('.photoDiv');
const imageId = $('#imageId').text(); // 从模板获取图片ID

if(etat === 'true'){
  const img = document.createElement("img");
  img.src = `/images/${imageId}`; // 接口地址
  img.height = 200;
  img.width = 200;
  photoDiv.append(img);
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 09:27:47