经过近 2 个工作日的谷歌搜索并尝试了我在整个网络上找到的几种不同的可能性,我在这里提出这个问题,希望我最终能得到答案。
首先,这就是我想要做的:
我正在开发一个客户端和一个服务器应用程序,目的是在单个服务器上的多个客户端之间交换大量大文件。客户端使用纯Java (JDK 1.6) 开发,而 Web 应用程序使用Grails (2.0.0) 完成。
由于客户端的目的是允许用户交换大量大文件(通常每个大约 2GB),我必须以某种方式实现它,以便上传可恢复,即用户能够停止和恢复上传随时。
这是我到目前为止所做的:
我实际上设法做我想做的事情并将大文件流式传输到服务器,同时仍然能够使用原始套接字暂停和恢复上传。我会向服务器发送一个常规请求(使用 Apache 的 HttpClient 库),让服务器向我发送一个可供我免费使用的端口,然后在服务器上打开一个 ServerSocket 并从客户端连接到该特定套接字。
这是问题所在:
实际上,这至少存在两个问题:
- 我自己打开这些端口,所以我必须自己管理打开和使用的端口。这是相当容易出错的。
- 我实际上绕过了 Grails 管理大量(并发)连接的能力。
最后,这是我现在应该做的事情和问题:
由于我上面提到的问题是不可接受的,我现在应该使用 Java 的 URLConnection/HttpURLConnection 类,同时仍然坚持使用 Grails。
连接到服务器并发送简单的请求完全没有问题,一切正常。当我尝试使用流(客户端中的连接的 OutputStream 和服务器中的请求的 InputStream)时,问题就开始了。打开客户端的 OutputStream 并向其写入数据非常简单。但是从请求的 InputStream 中读取对我来说似乎是不可能的,因为它看起来总是空的。
示例代码
这是服务器端(Groovy 控制器)的示例:
def test() {
InputStream inStream = request.inputStream
if(inStream != null) {
int read = 0;
byte[] buffer = new byte[4096];
long total = 0;
println "Start reading"
while((read = inStream.read(buffer)) != -1) {
println "Read " + read + " bytes from input stream buffer" //<-- this is NEVER called
}
println "Reading finished"
println "Read a total of " + total + " bytes" // <-- 'total' will always be 0 (zero)
} else {
println "Input Stream is null" // <-- This is NEVER called
}
}
这是我在客户端(Java 类)所做的:
public void connect() {
final URL url = new URL("myserveraddress");
final byte[] message = "someMessage".getBytes(); // Any byte[] - will be a file one day
HttpURLConnection connection = url.openConnection();
connection.setRequestMethod("GET"); // other methods - same result
// Write message
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(message);
out.flush();
out.close();
// Actually connect
connection.connect(); // is this placed correctly?
// Get response
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = null;
while((line = in.readLine()) != null) {
System.out.println(line); // Prints the whole server response as expected
}
in.close();
}
正如我所提到的,问题在于它request.inputStream
总是产生一个空的 InputStream,所以我永远无法从中读取任何内容(当然)。但这正是我想要做的(所以我可以流式传输要上传到服务器的文件,从 InputStream 中读取并将其保存到文件中),这相当令人失望。
我尝试了不同的 HTTP 方法,不同的数据负载,还一遍遍地重新排列代码,但似乎无法解决问题。
我希望找到什么
当然,我希望找到解决我的问题的方法。任何东西都会受到高度赞赏:提示、代码片段、库建议等等。也许我什至都错了,需要朝着完全不同的方向前进。
那么,如何在不手动打开服务器端端口的情况下实现从 Java 客户端到 Grails Web 应用程序的相当大(二进制)文件的可恢复文件上传?