最近上传阿里云的时候同一个文件上传两个服务地址,第一个文件读取以后第二个再去读取就拿不到了。代码如下:

   //内网上传OSS获取key值
String ossKey = OSSClientUtil.getOSSURL(endpoint, accessKeyId, accessKeySecret, bucketName, key, inputStream);
//外网上传OSS获取key值
String outOssLink = OSSClientUtil.getOutOSSLink(outEndpoint, outAccessKeyId, outAccessKeySecret, outBucketName, key,
inputStream); 

导致第二次上传失败。

Java中的Inputstream是不能重复读取的。
但是有没有想过,InputStream为什么不能重复读呢?
其实要回答“为什么”这个问题很简单,就是人家接口就是这么设计的,不能重复读。
所以今天要讨论的问题更像是:Java的InputStream为什么要设计为不能重复读?
关于InputStream为什么不能重复读取,网上也各有说法:
有的同学说:
“InputStream就类比成一个杯子,杯子里的水就像InputStream里的数据,你把杯子里的水拿出来了,杯子的水就没有了,InputStream也是同样的道理。”
比喻的非常好,让我们从直观上认识了InputStream为什么不能重复被读。
也有的同学从更深的代码角度去分析:
“在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会重置。”
说的也有道理,就是说InputStream的读取是单向的。但是并不是所有的InputStream实现类都是这样的实现方式。

Java 的List内部是使用数组实现的,遍历的时候也有一个pos指针。但是没有说List遍历一个第二次遍历就没有了。第二次遍历是创建新的Iterator,所以pos也回到了数组起始位置。对于某些InputStream当然可以也这么做。例如:ByteArrayInputStream
ByteArrayInputStream就是将一个Java的byte数组保存到对象里,然后读取的时候遍历该byte数组。

更改以后的代码如下:

public class InputStreamFactory {

    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
private byte[] buffer = new byte[1024]; public InputStreamFactory(InputStream input) throws IOException {
int len;
while ((len = input.read(buffer)) > -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
} public InputStream newInputStream() {
return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
} }

更改代码:

  InputStreamFactory inputStreamFactory = null;
try {
inputStreamFactory = new InputStreamFactory(inputStream);
//内网上传OSS获取key值
String ossKey = OSSClientUtil.getOSSURL(endpoint, accessKeyId, accessKeySecret, bucketName, key,
inputStreamFactory.newInputStream());
//外网上传OSS获取key值
String outOssLink = OSSClientUtil.getOutOSSLink(outEndpoint, outAccessKeyId, outAccessKeySecret, outBucketName,
key, inputStreamFactory.newInputStream());
} catch (IOException e) {
log.info("读取文件流失败", e);
}

  

InputStream为什么不能被重复读取?的更多相关文章

  1. InputStream流无法重复读取的解决办法

    前言:今天工作的需要需要读取aws云上S3桶里面的PDF数据,第一步能够正常的获取PDF文件的InputStream流,然后,我为了测试使用了IOUtils.toString(is)将流System. ...

  2. Java 利用 ByteArrayOutputStream 和 ByteArrayInputStream 避免重复读取配置文件

    最近参与了github上的一个开源项目 Mycat,是一个mysql的分库分表的中间件.发现其中读取配置文件的代码,存在频繁多次重复打开,读取,关闭的问题,代码写的很初级,稍微看过一些框架源码的人,是 ...

  3. 拦截器中,request中getReader()和getInputStream()只能调用一次,构建可重复读取inputStream的request.

    由于 request中getReader()和getInputStream()只能调用一次 在项目中,可能会出现需要针对接口参数进行校验等问题. 因此,针对这问题,给出一下解决方案 实现方法:先将Re ...

  4. SpringMvc上传文件遇到重复读取InputStream的问题

    文件上传配置: <bean id="multipartResolver" class="org.springframework.web.multipart.comm ...

  5. ServletInputStream的重复读取(多次读取)(转)

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  6. 多线程下不重复读取SQL Server 表的数据

    在进行一些如发送短信.邮件的业务时,我们经常会使用一个表来存储待发送的数据,由后台多个线程不断的从表中读取待发送的数据进行发送,发送完成后再将数据转移到历史表中,这样保证待发送表的数据一般情况下不会太 ...

  7. ASP.NET Core重复读取Request.Body

    //HttpContext context.Request.EnableRewind(); //创建缓冲区存放Request.Body的内容,从而允许反复读取Request.Body的Stream u ...

  8. Java实现inputstream流的复制

    获取到一个inputstream后,可能要多次利用它进行read的操作.由于流读过一次就不能再读了,而InputStream对象本身不能复制,而且它也没有实现Cloneable接口,所以得想点办法. ...

  9. java HttpServletRequest 重复流读取

    在用reset接口的时候,常常会使用request.getInputStream()方法,但是流只能读取一次,一旦想要加上一个过滤器用来检测用户请求的数据时就会出现异常.   在过滤器中通过流读取出用 ...

随机推荐

  1. 前端之HTML(一)

    最近学到前端的一些知识,感觉挺有意思的.总结一下常用的知识.这些只是最简单的东西. 一 HTML,CSS,JS的关系 一个基本的网站包含很多网页,一个网页又有html,css,js组成. html 是 ...

  2. 如何做出一个更好的Machine Learning预测模型【转载】

    作者:文兄链接:https://zhuanlan.zhihu.com/p/25013834来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 初衷 这篇文章主要从工程角度来 ...

  3. 潭州课堂25班:Ph201805201 django框架 第一课 环境搭建 (课堂笔记)

    在虚拟机中创建虚拟环 mkvirtualenv -p /usr/bin/python3 djtest mkvirtualenv 是创建命令, -p /usr/bin/python3  是指定在 pyt ...

  4. shell脚本使用技巧4--读取字符,重复执行

    ls | cat -n > out.txt 给输出的信息加行号并导出到out.txt 利用shell生成一个独立的进程 pwd; (cd /bin; ls); pwd; 开启一个子shell,不 ...

  5. 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第4章编程练习9

    #include <iostream>#include <string>using namespace std;struct CandyBar{ //string kind;  ...

  6. iOS自动布局的学习

    Autolayout: 最重要的两个概念: 约束:对控件位置和大小的限定条件 参照:对控件设置的约束是相对于哪一个视图而言的 自动布局的核心计算公式: obj1.property1 =(obj2.pr ...

  7. std::string 用法总结

    标准C++中的string类的用法总结 相信使用过MFC编程的朋友对CString这个类的印象应该非常深刻吧?的确,MFC中的CString类使用起来真的非常的方便好用.但是如果离开了MFC框架,还有 ...

  8. domReady

    function myReady(fn){ //对于现代浏览器,对DOMContentLoaded事件的处理采用标准的事件绑定方式 if ( document.addEventListener ) { ...

  9. 深入理解javascript构造函数和原型对象

    ---恢复内容开始--- 对象,是javascript中非常重要的一个梗,是否能透彻的理解它直接关系到你对整个javascript体系的基础理解,说白了,javascript就是一群对象在搅..(哔! ...

  10. Asp.Net HttpPostedFile和base64两种上传图片(文件)方式

    之前上传图片基本都是用的HttpPostedFile方式获取图片,这次因为需求关系,要对准备上传的图片进行删除,最后提交的时候才去保存图片到服务器, 找了下资料,html5有个新的东西出来,js 里面 ...