问题说明
因为项目需求,需要从一个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());
大家还有什么解决方案可以探讨一下?我也学习学习。