关于Java/Kotlin下载图片,图片打开不能显示问题探究

图片下载其实是个很简单的功能,通过IO流从在线地址获取流,之后将流输出到文件即可完成下载功能,但是,最近我发现某个网站中的图片下载成功,但是打开却是无法打开,这让我迷惑,百度上根本就没有人说清楚

今天,通过研究和朋友的讨论,终于是找到了答案,至于答案是什么,请耐心往下阅读~

问题出现

测试的图片地址为http://www.xbiquge.la/files/article/image/10/10489/10489s.jpg

下载图片代码Java版:

URL url = new URL("http://www.xbiquge.la/files/article/image/10/10489/10489s.jpg");
URLConnection connection=url.openConnection();//打开链接
InputStream inputStream = connection.getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File("e:\\test.jpg")));
int c;
byte[] temp = new byte[1024 * 2];//提供个缓冲区
while ((c = bufferedInputStream.read(temp)) != -1) {
    bufferedOutputStream.write(temp,0,c);//读多少,写多少
}
bufferedOutputStream.close();
inputStream.close();

下载代码Kotlin版:

val file =File("e:\\test.jpg")
val openConnection = URL("http://www.xbiquge.la/files/article/image/10/10489/10489s.jpg").openConnection()
val bytes = openConnection.getInputStream().readBytes()
file.writeBytes(bytes)

我们通过上面的对比,明显可以看到Kotlin的代码比Java的要简洁不少

上面的代码都是没错,把图片下载下来,打开如下图显示

之后用浏览器打开,用另存为保存图片,图片是可以正常打开的

用迅雷测试,也是打不开,问题似乎找不到原因了

不甘心认输的我,去搜索了一下,添加了各种请求头,但还是无效,似乎到了死胡同了

原因

没办法,只好去向学习群里的大佬们请教了

“哎,这个图片还可以解压,里面有图片!”群里名为夜深的网友说道。

?!我将图片的扩展名改为了zip,之后解压,果不其然发现了可以正常打开的图片

我们知道了下载下来的文件是个压缩包,这样问题也是得到了解决方法,但是,为什么会这样呢?

刚好和python的大佬聊到了这个问题,他试了一下,python可以正确获得到图片,为什么java就不行?经过讨论,从请求头发现了原因,如下图

原来是因为网站在响应的时候返回的是GZIP压缩过的文件流,而采用此方式的话可以减少用户浏览网页的等待时间

python和浏览器都是内置了自动解压缩的功能,所以,这就是为什么浏览器可以查看图片,python也可以得到正确图片的原因

解决方法

针对gzip文件流

这里我们只需要使用GZIPInputStream包装一下InputStream,之后再输出即可,这里我只贴kotlin版的代码,Java的话参考一下来改吧

val file =File("e:\\test.jpg")
val openConnection = URL("http://www.xbiquge.la/files/article/image/10/10489/10489s.jpg").openConnection()
val bytes = GZIPInputStream(openConnection.getInputStream()).readBytes()
file.writeBytes(bytes)

通用下载图片方法

由于我们所要下载的图片,可能服务器返回的是未压缩的图片,如果我们继续使用上面的方法就会报错

所以我们需要加个判断,判断输入流是否为压缩过的

这里我就直接封装成一个方法了

fun downloadImage(url: String, file: File): File {
    val openConnection = URL(url).openConnection()
    //防止某些网站跳转到验证界面
    openConnection.addRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36")
    //如果图片是采用gzip压缩
    val bytes = if (openConnection.contentEncoding == "gzip") {
        GZIPInputStream(openConnection.getInputStream()).readBytes()
    } else {
        openConnection.getInputStream().readBytes()
    }
    file.writeBytes(bytes)
    return file
}

参考

How to check if InputStream is Gzipped? stackflow

原文地址:https://www.cnblogs.com/stars-one/p/12358486.html

时间: 2024-07-31 17:06:29

关于Java/Kotlin下载图片,图片打开不能显示问题探究的相关文章

服务端通知浏览器以下载的方式打开图片

import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServ

java如果模拟请求重启路由器(网络爬虫常用),还有java如何下载图片

我们如果在公司或家里使用网络爬虫去抓取自己索要的一些数据的时候,常常对方的网站有defence机制,会给你的http请求返回500错误,只要是相同IP就请求不到数据,这时候我们只能去重启路由器,这样IP地址会改变,网络爬虫就能正常工作了 下面是通过发送Socket请求来模拟路由器的重启指令: protected void rebotadsl() { try { BufferedOutputStream sender = null; String url = baseURL; URL target

java 抓取网页图片

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

java画图程序_图片用字母画出来_源码发布_版本二

在上一个版本:java画图程序_图片用字母画出来_源码发布 基础上,增加了图片同比例缩放,使得大像素图片可以很好地显示画在Notepad++中. 项目结构: 运行效果1: 原图:http://images.cnblogs.com/cnblogs_com/hongten/356471/o_imagehandler_result1.png 运行效果2: 原图:http://images.cnblogs.com/cnblogs_com/hongten/356471/o_imagehandler_res

java指纹识别+谷歌图片识别技术

Google "相似图片搜索":你可以用一张图片,搜索互联网上所有与它相似的图片. 打开Google图片搜索页面: 点击使用上传一张angelababy原图: 点击搜索后,Google将会找出与之相似的图片,图片相似度越高就越排在前面.如: 这种技术的原理是什么?计算机怎么知道两张图片相似呢? 根据Neal Krawetz博士的解释,实现相似图片搜素的关键技术叫做"感知哈希算法"(Perceptualhash algorithm),它的作用是对每张图片生成一个&qu

从网络下载的图片加缓存功能

从网络中下载的图片放到本地,然后在用bitmap获取本地的图片,通过消息队列发送到主线程去执行, 最后一步我们要判断一下,如果这个文件存在,直接从本地来读取,如果不存在就从网络中获取. package com.example.getimg; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; imp

java实现生成简单图片验证码

原文:java实现生成简单图片验证码 源代码下载地址:http://www.zuidaima.com/share/1550463428840448.htm 项目载图: 该项目要转换为Dynamic web project http://www.zuidaima.com/blog/1618162161323008.htm 另外缺少jar包: http://www.zuidaima.com/jar/search/jstl-1.0.1.htm http://www.zuidaima.com/jar/s

java画图程序_图片用字母画出来_源码发布

在之前写了一篇blog:java画图程序_图片用字母画出来 主要是把一些调试的截图发布出来,现在程序调试我认为可以了(当然,你如果还想调试的话,也可以下载源码自己调试). 就把源码发布出来. 项目结构: 资源文件: 原图:http://images.cnblogs.com/cnblogs_com/hongten/356471/o_imagehandler_resource.png 运行效果: 原图:http://images.cnblogs.com/cnblogs_com/hongten/356

dede不能下载远程图片及如何实现图片本地化的方法

有些时候我们想保存图片到本地服务器的时候发现保存不了,比如我们自己拷贝自己的站点到另外一个服务器等等,下面3A网络的小钱就来分享Dedecms无法保存远程图片到本地服务器的解决方法,分享给大家供大家参考.具体分析如下: 一.开启远程图片本地化 在编辑区域上方有个附加选项:下载远程图片和资源,把这个选上即可!也在可以在系统设置里面的其他选项把:远程图片本地化这个项目给选上! 二.检查网站目录 上传图片目录中是否有allimg这个文件夹(当更改了图片上传目录的情况下最容易出现这个问题) 三.可能是因