如何在Java中为图像创建HTTP响应?

huangapple go评论70阅读模式
英文:

How to create a http response for images in java?

问题

我一直在尝试创建一个简单的Java Web服务器,对于像HTML或CSS这样的文件,一切都运行正常,但我无法正确地发送图像响应。问题显然出现在我发送的图像数据上,但我不确定如何正确处理它。我已经搜索了很长时间的相关信息,但是我无法找到任何有用的内容来解决我的问题。

我的代码的一部分:

public void Send(String path) throws IOException {
    File file = new File(path);
    if (file.exists()) {
        if (!file.isDirectory()) {
            if (isImage(file)) {
                InputStream is = new FileInputStream(file);
                byte[] bytes = IOUtils.toByteArray(is);
                String response = "HTTP/1.1 200 OK" + CRLF + "Content-Length: " + bytes.length + CRLF;
                response += "content-type: image/jpeg" + CRLF + CRLF;
                outputStream.write(response.getBytes());
                outputStream.write(bytes);
                outputStream.write((CRLF + CRLF).getBytes());
                outputStream.flush();
            } else {
                // ... 处理非图像文件的逻辑 ...
            }
            return;
        }
    }
    SendError("404 Not Found");
}

outputStream 是来自 Socket 的 OutputStream。

我看到了这个链接,但我认为我至少在图像部分只是使用了流。

我是新手,所以任何帮助都将不胜感激!

编辑(更多信息):

浏览器信息:

Headers

Preview

isImage(file) 方法正常工作,我已经进行了测试,但这里是代码:

private boolean isImage(File file) {
    String mimetype = new MimetypesFileTypeMap().getContentType(file);
    String type = mimetype.split("/")[0];
    return type.equals("image");
}

图像文件是 2.jpg。

编辑 2:

我编写了以下代码,将数组的内容写入文本文件:

String out = "";
for (int i = 0; i < bytes.length; i++) {
    if (i % 16 == 0) {
        out += "\n";
    }
    out += String.format("%02X ", bytes[i]);
}
BufferedWriter writer = new BufferedWriter(new FileWriter("test.txt"));
writer.write(out);
writer.close();

所以我检查了图像和数组的开头,它们似乎是相同的。

Image data 的开头

array 的开头

之后,我尝试创建一个用于测试的客户端:

private static void Get2(String link) throws IOException {
    URL url = new URL(link);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    // ... 设置请求属性 ...
    int status = con.getResponseCode();
    // ... 读取响应内容 ...
}

我调用了函数:Get2("http://localhost:8080/images/2.jpg");

然后在 test2.txt 中保存了数据。在里面,我看到了一些相似数据的部分,但显然有些问题。我不确定我是否错误地使用了这个客户端测试,所以如果我做错了什么,或者应该使用其他方法,请让我知道。

图像(左边是 test2.txt,右边是 test.txt)

感谢每个帮助过我的人,或者已经提供了任何建议的人。

英文:

I have been trying to create a simple java web server everything works fine for files such as html or css but I'm unable to send image responses correctly. The problem is obviously with the image data that I'm sending but I'm not sure how to do it properly. I have been searching for any information about it for a long time not and I just can't find anything useful that would fix my problem.

Part of my code:

public void Send(String path) throws IOException {
	File file = new File(path);
	if(file.exists()) {
		if(!file.isDirectory()) {
			if(isImage(file)) {
				InputStream is = new FileInputStream(file);
				byte[] bytes = IOUtils.toByteArray(is);
				String response = &quot;HTTP/1.1 200 OK&quot; + CRLF + &quot;Content-Length: &quot; + bytes.length + CRLF;
				response += &quot;content-type: image/jpeg&quot; + CRLF + CRLF;
				outputStream.write(response.getBytes());
				outputStream.write(bytes);
				outputStream.write((CRLF + CRLF).getBytes());
				outputStream.flush();
			} else {
				String data = &quot;&quot;;
				BufferedReader br = new BufferedReader(new FileReader(file));
				String st;
				while ((st = br.readLine()) != null) {
					data += st;
				}
				int length = data.getBytes().length;
				String response = &quot;HTTP/1.1 200 OK&quot; + CRLF + &quot;Content-Length: &quot; + length + CRLF;
				response += CRLF + data + CRLF + CRLF;
				br.close();
				outputStream.write(response.getBytes());
			}
			return;
		}
	}
	SendError(&quot;404 Not Found&quot;);
}

> outputStream is OutputStream from a Socket.

I saw this but I think I'm only using streams at least for the image part.

I'm new to this so any help would be appreciated!

EDIT (more inforamtion):

Browser information:

Headers

Preview

The isImage(file) methode works fine I have tested it but here it is:

private boolean isImage(File file) {
    String mimetype = new MimetypesFileTypeMap().getContentType(file);
    String type = mimetype.split(&quot;/&quot;)[0];
    return type.equals(&quot;image&quot;);
}

And the image is 2.jpg

EDIT 2

I wrote this code to write the content of the array in a text file:

String out = &quot;&quot;;
for(int i = 0; i &lt; bytes.length; i++) {
	if(i%16 == 0) {
		out += &quot;\n&quot;;
	}
	out += String.format(&quot;%02X &quot;, bytes[i]);
}
BufferedWriter writer = new BufferedWriter(new FileWriter(&quot;test.txt&quot;));
writer.write(out);
writer.close();

So I checked the start of both the image and the array and they seem to be identical.

Start of the image data

Start if the array

After that I tried to create a client for testing:

private static void Get2(String link) throws IOException {
	URL url = new URL(link);
	HttpURLConnection con = (HttpURLConnection) url.openConnection();
	con.setRequestMethod(&quot;GET&quot;);
	con.setRequestProperty(&quot;Connection&quot;, &quot;keep-alive&quot;);
	con.setRequestProperty(&quot;User-Agent&quot;, &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36 Edg/85.0.564.68&quot;);
	con.setRequestProperty(&quot;Accept&quot;, &quot;image/webp,image/apng,image/*,*/*;q=0.8&quot;);
	con.setRequestProperty(&quot;Sec-Fetch-Site&quot;, &quot;same-origin&quot;);
	con.setRequestProperty(&quot;Sec-Fetch-Mode&quot;, &quot;no-cors&quot;);
	con.setRequestProperty(&quot;Sec-Fetch-Dest&quot;, &quot;image&quot;);
	con.setRequestProperty(&quot;Accept-Encoding&quot;, &quot;gzip, deflate, br&quot;);
	con.setRequestProperty(&quot;Accept-Language&quot;, &quot;sl,en;q=0.9,en-GB;q=0.8,en-US;q=0.7&quot;);
	
	con.setConnectTimeout(5000);
	con.setReadTimeout(5000);
	
	con.setInstanceFollowRedirects(false);
	
	int status = con.getResponseCode();
	
	BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
	String inputLine;
	StringBuffer content = new StringBuffer();
	int i = 0;
	while ((inputLine = in.readLine()) != null) {
		if(i &lt; 5) {
			System.out.println(inputLine);
		} else {
		    content.append(inputLine);
		}
		i++;
	}
	in.close();
	con.disconnect();

	BufferedWriter writer = new BufferedWriter(new FileWriter(&quot;test2.txt&quot;));
	writer.write(content.toString());
	writer.close();
}

> I called the function: Get2("http://localhost:8080/images/2.jpg");

And got saved data in the test2.txt. Inside I saw some parts of similar data but it's clearly something wrong with it. I'm not sure if I'm using this client test wrong so if I'm doing something wrong or should be using something else let me know.

Image (left test2.txt, right test.txt)

Thanks to everyone that will and already helped or had any suggestions.

答案1

得分: 0

<strike>我终于弄明白了。实际上,我没有提供所有的东西,是我的错。

&gt; String CRLF = &quot;\n\r&quot;;

但显然,应该只有 \n。

我在某个地方看到过,Windows 在 \n 之后会自动添加 \r。我不知道这是否正确,但移除 \r 解决了我的问题,因为之前在 `GET / HTTP/1.1` 后面有两行空行,所以其他内容被视为数据的一部分。</strike>

一旦我改变了那个,一切都正常工作了。
再次感谢你的帮助!

编辑

没关系。我做错的是 \n 和 \r 的顺序。应该是 `\r\n` 而不是 `\n\r`
英文:

<strike>I finally figured it out. Actually my bad for not providing everything.

> String CRLF = "\n\r";

But apparently, it should only be \n.

I read somewhere that windows automatically adds \r after \n. I don't know if that's true but removing \r fixed my problem as before I had 2 empty lines right after GET / HTTP/1.1 so the other content was considered as part of the data.</strike>

As soon as I changed that everything worked fine.
Again thanks for your help!

EDIT

Nevermind. What I did wrong was the order of \n and \r. It should be \r\n not \n\r

huangapple
  • 本文由 发表于 2020年10月6日 19:14:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/64224655.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定