还在用InputStream的available()方法获取流的字节数吗?那你可要小心了!

问题说明

因为项目需求,需要从一个url获取文件流然后保存到minio文件服务器中。

先看看下面的代码片段

MinioClient minioClient = MinioClient.builder()
                .endpoint(new URL("http://ip:port"))
                .credentials("username", "password")
                .build();
String urlStr = "url";
URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(3000);
conn.setRequestMethod("GET");
        conn.setRequestProperty("User-Agent", "Mozilla/5.0");
        conn.setRequestProperty("Content-Type", "application/octet-stream");
InputStream inputStream = conn.getInputStream();
minioClient.putObject(PutObjectArgs.builder()
                .object("objectpath")
                .bucket("bid")
                .contentType("application/octet-stream")
                .stream(inputStream, inputStream.available(), -1)
                .build());

就是简单的从url获取到输入流,然后上传到minio。我写完之后看着没问题了,就开始测试了。

我先是从url获取一个pdf文件流,然后上传。奇怪的事情就发生了,上传的pdf文件下载下来打不开,提示“文件已损坏”。

然后按照上面的方式试了一个world文件,结果还是打不开。完犊子了,这代码看着也没问题啊,奇了怪了。

查找问题

会是什么问题呢?没有获取到流?还是上传的代码写错了?

因为项目一直就用上面代码的方式去上传文件的啊,要是有问题肯定早就有问题了啊,这个排除掉。

你说没有获取到流也不对啊,因为确实是上传了一个文件,只是打不开罢了。

所以,最后将问题定位到获取到的流肯定没有上传完整。

就去看两个文件的大小,确实是这样,只上传了一部分上去。

那么,问题就出现在inputStream.available()这块了,因为minio的stream方法的第二个参数是指定上传多少个字节。

查找资料

最近chatgpt比较火嘛,那就去问问它。
在这里插入图片描述
可见,available()方法能去判断流中有没有字节可读。但是,并不能得到流的精确总字节数。

解决方案

还是找chatgpt吧,毕竟很强大。

InputStream inputStream = // 实例化你的 InputStream 对象

byte[] buffer = new byte[1024];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
    totalBytesRead += bytesRead;
}

System.out.println("总字节数: " + totalBytesRead);

我自己的思路是要创建一个ByteArrayOutputStream缓存区去将所有的字节保存起来,然后要将ByteArrayOutputStream的总字节数传递给minio。

上代码

MinioClient minioClient = MinioClient.builder()
                .endpoint(new URL("http://ip:port"))
                .credentials("username", "password")
                .build();
        String urlStr = "url";
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(3000);
        conn.setRequestMethod("GET");
        conn.setRequestProperty("User-Agent", "Mozilla/5.0");
        conn.setRequestProperty("Content-Type", "application/octet-stream");
        InputStream inputStream = conn.getInputStream();
        // 加入缓存
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inputStream.read(buffer)) > -1 ) {
            byteArrayOutputStream.write(buffer, 0, len);
        }
        byteArrayOutputStream.flush();
        minioClient.putObject(PutObjectArgs.builder()
                .object("objectpath")
                .bucket("bid")
                .contentType("application/octet-stream")
                .stream(inputStream, byteArrayOutputStream.size(), -1)
                .build());

大家还有什么解决方案可以探讨一下?我也学习学习。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值