V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
LeeReamond
V2EX  ›  问与答

前端如何用 Post 方法显示一张图片?

  •  
  •   LeeReamond · 2021-02-13 18:19:18 +08:00 · 1618 次点击
    这是一个创建于 1383 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,前端框架 vue,在写验证码功能时遇到问题。

    正常的验证码显示,假设验证码路由为 /api/captcha 的话,如果用下面这种方式可以正常显示

    <v-img
      width="200px"
      src="/api/captcha"
    >
    </v-img>
    

    但是想到 captcha 申请需要同时发送一些信息,比如是谁在请求验证码,所以最好还是用 post 的方式来保证安全。

    后端改一下路由方法就行,而前端百度了一下,思路应该是将返回的二进制图片数据转成 base64,html 就能解析了。

    用了以下代码,结果不能正常显示

    that.$axios.post({
      url:'rand'
    })
    .then(response => Buffer.from(response.data, 'binary').toString('base64'))
    .then(data => {this.src = data})
    

    我打印了 bas64 编码后的文本,尝试解码进行校验, 解码后前几位字符为

    \xfdPNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01"\x00\x00\x00J\x08\x02\x00\x00\x00\xfd
    

    真实字符应该是

    \x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01"\x00\x00\x00J\x08\x02\x00\x00\x00\x90
    

    可以看到个别字符变成了别的东西,不太懂是怎么回事,有没有大佬解惑,谢谢

    9 条回复    2021-02-14 22:38:30 +08:00
    oott123
        1
    oott123  
       2021-02-13 18:33:30 +08:00 via Android
    确实应该是 0x89,怎么变了的不清楚需要更细节的东西,但是你这个 Buffer 是哪儿来的,nodejs 吗?

    更好的办法是 createObjectURL
    learningman
        2
    learningman  
       2021-02-13 18:36:57 +08:00 via Android
    你是想 base64 拼接 datauri?
    楼上说的 blob 确实更好的
    zzk1989
        3
    zzk1989  
       2021-02-13 18:50:16 +08:00
    base64 的图片不是"data:image/"开头的吗?

    如果后端不能改接口执意返回图片的情况下有一种古董的方案:
    用 iframe 来显示图片,
    用 js 生成并提交一个 form target=${iframe 的 name}
    这样接口返回的图片内容会在 iframe 里面显示
    LeeReamond
        4
    LeeReamond  
    OP
       2021-02-13 18:51:18 +08:00
    @oott123 我不熟悉 js,不太清楚 buffer 是哪来的,网上搜来答案都这么写,也确实不用定义直接就能创建,我估计应该是个 js 内建对象。

    我尝试了一下你说的 createobjecturl
    .then(response => {
    console.log(URL.createObjectURL(response.data))
    }
    这么写了一下得到了报错
    iPumpkin
        5
    iPumpkin  
       2021-02-13 18:54:21 +08:00   ❤️ 1
    ```
    const responseType = response.config.responseType

    if (responseType === 'blob') {
    return URL.createObjectURL(new Blob([response.data]))
    }

    if (responseType === 'arraybuffer') {
    const image = btoa(new Uint8Array(response.data).reduce((data, byte) => data + String.fromCharCode(byte), ''))
    const mimetype = response.headers['content-type'].toLowerCase()
    return `data:${mimetype};base64,${image}`
    }
    ```
    oott123
        6
    oott123  
       2021-02-13 18:56:57 +08:00 via Android   ❤️ 1
    那你就在请求的参数里面( url:那行下面)加一个 responseType: 'blob' 吧,用不用 createObjectURL 都可以解决你的问题

    这样我明白为什么 x89 变成 xfd 了,因为以 UTF8 解码了

    另外 Buffer 不是 js 的内建对象(是 nodejs 的),所以你能用肯定是有什么 browserify 之类的玩意儿在帮你(但不重要了)
    treblex
        7
    treblex  
       2021-02-13 20:11:04 +08:00 via iPhone
    🤪http 规范有什么不清楚的地方吗,post 和 get 的语义有什么不清楚的吗

    抱歉,我对这种问题实在有太大的恶意了,主要是因为公司的后端对这个没有概念,写的破接口太烦了,🌚
    kyuuseiryuu
        8
    kyuuseiryuu  
       2021-02-14 11:40:10 +08:00 via iPhone
    先 post 提交数据,然后 API 返回图片链接就好了呀。
    weixiangzhe
        9
    weixiangzhe  
       2021-02-14 22:38:30 +08:00 via Android
    直接改成 get 不行吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3861 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 04:17 · PVG 12:17 · LAX 20:17 · JFK 23:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.