如何将 Http url (image URL) 转换为字节缓冲区或字节?

How to convert Http url (image URL) to byte buffer or in byte?

我尝试了一些函数将 url 图像转换为字节缓冲区,但它不起作用。它显示 IOException 错误

String imagePath = "https://www.clearias.com/up/UPSC-Civil-Services-Mains-Exam-2018-Timetable-V1.png";

尝试 1:

URL u = new URL(imagePath);
int contentLength = u.openConnection().getContentLength();
InputStream openStream = u.openStream();
byte[] binaryData = new byte[contentLength];
openStream.read(binaryData);
ByteBuffer imageBytes = ByteBuffer.wrap(openStream);

当我将 openStream 包装到 ByteBuffer 时显示错误

"The method wrap(byte[]) in the type ByteBuffer is not applicable for the arguments (InputStream)"

尝试2:

    URL url = new URL(imagePath);
    ByteArrayOutputStream output = new ByteArrayOutputStream();

    try (InputStream inputStream = url.openStream()) {
        int n = 0;    
        byte[] buffer = new byte[1024];    
        while (-1 != (n = inputStream.read(buffer))) {
            output.write(buffer, 0, n);
        }
    }
    byte[] img = output.toByteArray();    
    ByteBuffer imageBytes = ByteBuffer.wrap(img);    

我也试过这个功能,但它显示这个错误:

java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.clearias.com/up/UPSC-Civil-Services-Mains-Exam-2018-Timetable-V1.png

尝试 3: 另一个是

byte[] img = Base64.encodeBase64(IOUtils.toByteArray((new URL(imagePath)).openStream()), true);    

这一行也给我错误

我想 URL 有问题。

使用 Apache commons-io Apache commons-io

下面是示例代码:

import org.apache.commons.io.IOUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;

public class DownloadImage {
    public static void main(String[] args) {

        try {
            URL url = new URL("https://en.wikipedia.org/wiki/Car#/media/File:401_Gridlock.jpg");
            System.out.println(Arrays.toString(downloadFile(url)));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    private 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) {
            e.printStackTrace();
        }
        return null;
    }
}

输出: [..., 47, 98, 111, 100, 121, 62, 10, 60, 47, 104, 116, 109, 108, 62, 10]

HTTP错误403表示服务器已经完全理解您请求并下载该图片的意图。但是,它估计你没有权利这样做,不是因为程序错误,而是因为你不应该被允许这样做。

通常结论应该是无法仅从其 URL 获取此图像,也许您需要在请求的同时提供某种形式的身份验证,以向服务器证明您应该允许获取图像。

然而很明显,仅通过 copy/pasting 浏览器中的 URL,在 "normal" 条件下服务器接受无条件提供图像。服务器只拒绝来自 Java 程序的请求(也许还有其他技术,我没有测试。)剩下的问题是,服务器如何判断请求是由 Java 程序?或者,更笼统地说,服务器如何决定您是否有权发出此请求?

理论上我们无法猜测每个人的意图,但对于想要拒绝来自特定技术的请求的 HTTP 服务器来说,通常会根据请求的 User-Agent HTTP header 来做到这一点。所以我决定修改Java默认发送的User-Agent,谎称请求是由Firefox完成的(以一种非常幼稚的方式)

代码如下:

URL url = new URL(imagePath);
ByteArrayOutputStream output = new ByteArrayOutputStream();
URLConnection conn = url.openConnection();
conn.setRequestProperty("User-Agent", "Firefox");

try (InputStream inputStream = conn.getInputStream()) {
  int n = 0;
  byte[] buffer = new byte[1024];
  while (-1 != (n = inputStream.read(buffer))) {
    output.write(buffer, 0, n);
  }
}
byte[] img = output.toByteArray();
ByteBuffer imageBytes = ByteBuffer.wrap(img);

有效。