V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
raiz
V2EX  ›  Android

android app 使用 webview 显示网页难免要对网页中的图片进行保存到本地的操作,看了一圈别人写的博客,都是用 `把图片再下载一遍` 的方式,图片在网页中已经被下载过了,再下载一遍让我感到很不合理,但是我找一圈,真找不到方法

  •  
  •   raiz · 2018-02-05 16:51:26 +08:00 · 9294 次点击
    这是一个创建于 2485 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如这篇文章: https://juejin.im/entry/5817f71abf22ec00689e4b8a webview 可以使能缓存机制,那图片应该是存在了文件系统的某个位置; 在应用目录下有一些 文件名是经过 hash 的文件,应该是对应的缓存文件, 至于 hash 的算法,根据 https://stackoverflow.com/a/27148985/5105007 这个回答,应该是不开放的; 如果 android 出于安全考虑不开放相关 api,那还有办法把 webview 里的图片读出来?

    9 条回复    2018-02-06 15:16:07 +08:00
    zapper
        1
    zapper  
       2018-02-05 17:17:27 +08:00
    注入 js 拦截图片吧
    Khlieb
        2
    Khlieb  
       2018-02-05 17:21:47 +08:00 via Android
    hxsf
        3
    hxsf  
       2018-02-05 17:30:01 +08:00
    我记得 webview 可以自己拦截所有请求的吧。正常代理这些请求,把响应中是图片的保存下来。
    shoaly
        4
    shoaly  
       2018-02-05 17:52:33 +08:00
    老老实实拿到连接, 然后重新下载吧.
    就算找到了接口, 安卓众多 ROM 的不同 你也做不了兼容和适配. 说不定同一个厂家的 ROM 升级之后你的 hack 方法也失效了. 不值当.
    why1
        5
    why1  
       2018-02-05 18:07:00 +08:00 via Android
    你断网再另存图片也是可以的
    Rheinmetal
        6
    Rheinmetal  
       2018-02-05 19:49:05 +08:00 via Android
    再下载一遍 不就是用缓存吗 多一个 304 而已 又不 费 流量
    flyingghost
        7
    flyingghost  
       2018-02-05 20:11:09 +08:00
    @Rheinmetal 兄台错矣,自己发请求下载要想得到 304,你得知道 Last-Modified/ETag 等信息,这些信息应该在 WebView 下面的缓存管理器里。再说即使得到 304,也还是要跟缓存管理器要 content。HTTPConnection 可不会自动帮你做这些事。(以上都是猜的未经验证)
    (可能)可行的办法是:
    1,自己做 WebView 的所有网络请求。顺带就可以自定义缓存并提供想要的任何接口了。
    2,把 img 画在 canvas 上再导出 base64 再还原成文件(虽然已经不是服务器上原本的那个文件了)。

    <script type="text/javascript">
    function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, img.width, img.height);

    var dataURL = canvas.toDataURL("image/png");
    console.log(dataURL);
    return dataURL
    }
    </script>
    <img crossOrigin="Anonymous" src="https://upload.ibesteeth.com/tmp/club/img/1513250107372f058df49.jpg" onclick="getBase64Image(this)"/>

    但这样的实现有一个安全问题:默认 canvas 是在本地匿名域上的,img 不是,而默认的安全模型是不允许直接导出的。这也是需要 crossOrigin="Anonymous"的原因。如果 WebView 有什么办法处理跨域问题,应该就可以用起来了。
    手头没有 Android 环境,lz 自己试试这个思路?
    KuroNekoFan
        8
    KuroNekoFan  
       2018-02-06 07:50:20 +08:00 via iPhone
    可以转成 base64 再传给 android
    raiz
        9
    raiz  
    OP
       2018-02-06 15:16:07 +08:00
    @flyingghost 谢谢, 对,webview 的缓存是隔离的。 两种思路我会去尝试,暂时先做其他内容。

    @KuroNekoFan 谢谢, 同#7 楼的方法二
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5642 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 03:20 · PVG 11:20 · LAX 19:20 · JFK 22:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.