我试图从URL读取图像(使用java包 java.net.URL )到一个byte []。 “Everything”工作正常,除了内容不是从流中被读取(图像损坏,它不包含所有图像数据)...字节数组被保存在数据库(BLOB)中。我真的不知道正确的方法是什么,也许你可以给我一个提示:)
这是我的第一种方法(代码格式化,删除了不必要的信息......):
URL u = new URL("http://localhost:8080/images/anImage.jpg");
int contentLength = u.openConnection().getContentLength();
Inputstream openStream = u.openStream();
byte[] binaryData = new byte[contentLength];
openStream.read(binaryData);
openStream.close();
我的第二个方法就是这个(因为你会看到内容长度是另一种方式):
URL u = new URL(content);
openStream = u.openStream();
int contentLength = openStream.available();
byte[] binaryData = new byte[contentLength];
openStream.read(binaryData);
openStream.close();
这两个代码都会导致图像损坏... 我已经阅读了这篇文章from stackoverflow
答案 0 :(得分:58)
无法保证您提供的内容长度实际上是正确的。尝试类似于以下内容的内容:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
baos.write(byteChunk, 0, n);
}
}
catch (IOException e) {
System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage());
e.printStackTrace ();
// Perform any other exception handling that's appropriate.
}
finally {
if (is != null) { is.close(); }
}
然后,您将获得baos
中的图像数据,您可以通过调用baos.toByteArray()
从中获取字节数组。
此代码未经测试(我只是在答案框中编写),但它与我认为你所追求的相当接近。
答案 1 :(得分:27)
用commons-io扩展Barnards的答案。单独回答因为我无法在评论中格式化代码。
InputStream is = null;
try {
is = url.openStream ();
byte[] imageBytes = IOUtils.toByteArray(is);
}
catch (IOException e) {
System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage());
e.printStackTrace ();
// Perform any other exception handling that's appropriate.
}
finally {
if (is != null) { is.close(); }
}
答案 2 :(得分:19)
这是一个干净的解决方案:
private byte[] downloadUrl(URL toDownload) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
byte[] chunk = new byte[4096];
int bytesRead;
InputStream stream = toDownload.openStream();
while ((bytesRead = stream.read(chunk)) > 0) {
outputStream.write(chunk, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
return outputStream.toByteArray();
}
答案 3 :(得分:11)
byte[] b = IOUtils.toByteArray((new URL( )).openStream()); //idiom
但请注意,上述示例中未关闭该流。
如果你想要一个(76个字符)的块(使用commons编解码器)......
byte[] b = Base64.encodeBase64(IOUtils.toByteArray((new URL( )).openStream()), true);
答案 4 :(得分:10)
我很惊讶这里没有人提到连接和读取超时的问题。它可能会发生(特别是在Android和/或一些糟糕的网络连接上)请求将挂起并永远等待。
以下代码(也使用Apache IO Commons)将此考虑在内,并等待最大值。 5秒,直到失败:
public static byte[] downloadFile(URL url)
{
try {
URLConnection conn = url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.connect();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(conn.getInputStream(), baos);
return baos.toByteArray();
}
catch (IOException e)
{
// Log error and return null, some default or throw a runtime exception
}
}
答案 5 :(得分:3)
使用commons-io IOUtils.toByteArray(URL):
String url = "http://localhost:8080/images/anImage.jpg";
byte[] fileContent = IOUtils.toByteArray(new URL(url));
Maven依赖项:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
答案 6 :(得分:1)
内容长度只是一个HTTP标头。你不能相信它。只需从流中读取所有内容即可。
可用肯定是错的。它只是可以在不阻塞的情况下读取的字节数。
另一个问题是您的资源处理。在任何情况下都必须关闭流。 try / catch / finally会做到这一点。
答案 7 :(得分:0)
指定超时很重要,尤其是在服务器需要响应时。使用纯Java,不使用任何依赖项:
public static byte[] copyURLToByteArray(final String urlStr,
final int connectionTimeout, final int readTimeout)
throws IOException {
final URL url = new URL(urlStr);
final URLConnection connection = url.openConnection();
connection.setConnectTimeout(connectionTimeout);
connection.setReadTimeout(readTimeout);
try (InputStream input = connection.getInputStream();
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
final byte[] buffer = new byte[8192];
for (int count; (count = input.read(buffer)) > 0;) {
output.write(buffer, 0, count);
}
return output.toByteArray();
}
}
使用依赖项,例如HC Fluent:
public byte[] copyURLToByteArray(final String urlStr,
final int connectionTimeout, final int readTimeout)
throws IOException {
return Request.Get(urlStr)
.connectTimeout(connectionTimeout)
.socketTimeout(readTimeout)
.execute()
.returnContent()
.asBytes();
}