1

我正在尝试使用 JavaURL类上传文件,并且我在 stack-overflow 上找到了一个先前的问题,它很好地解释了细节,所以我尝试遵循它。以下是我从答案中给出的代码片段中采用的代码。

我的问题是,如果我不调用connection.getResponseCode()connection.getInputStream()connection.getResponseMessage()或任何与服务器响应相关的任何内容,则该请求将永远不会发送到服务器。为什么我需要这样做?或者有什么方法可以在没有得到响应的情况下写入数据?

PS 我开发了一个服务器端上传 servlet,它接受multipart/form-data并将其保存到使用FileUpload. 它很稳定,绝对可以正常工作,所以这不是我的问题产生的地方。

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.io.IOUtils;

public class URLUploader {

    public static void closeQuietly(Closeable... objs) {
        for (Closeable closeable : objs) {
            IOUtils.closeQuietly(closeable);
        }
    }

    public static void main(String[] args) throws IOException {
        File textFile = new File("D:\\file.zip");
        String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.

        HttpURLConnection connection = (HttpURLConnection) new URL("http://localhost:8080/upslet/upload").openConnection();
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        OutputStream output = connection.getOutputStream();

        PrintWriter writer = new PrintWriter(output, true);
        // Send text file.
        writer.println("--" + boundary);
        writer.println("Content-Disposition: form-data; name=\"file1\"; filename=\"" + textFile.getName() + "\"");
        writer.println("Content-Type: application/octet-stream");
        FileInputStream fin = new FileInputStream(textFile);
        writer.println();
        IOUtils.copy(fin, output);
        writer.println();
        // End of multipart/form-data.
        writer.println("--" + boundary + "--");
        output.flush();
        closeQuietly(fin, writer, output);
        // Above request will never be sent if .getInputStream() or .getResponseCode() or .getResponseMessage() does not get called.
        connection.getResponseCode();
    }
}
4

3 回答 3

1

HttpURLConnection 有一堆影响请求的设置器,因此它需要知道您何时完成构建请求,以便将其发送出去。它执行此操作的方式是等到您实际从请求中请求返回某些内容,例如 InputStream。(这可以说是一个设计缺陷。)这也是为什么 setter “如果已经连接”会抛出 IllegalStateException 的原因——一旦你调用了一个 getter,连接就建立了,但调用 setter 为时已晚。

您应该能够调用getInputStream()然后就调用close()它而无需实际读取它。

于 2010-12-22T01:48:39.190 回答
0

对于那些正在检查此代码段的人,我认为有一句话是错误的:

OutputStream output = output = connection.getOutputStream();

检查一下 ;)
顺便说一句,当你建立连接时,你确实必须使用getResponseCode()方法来尝试处理异常,这样可以确保你的连接正常工作。

于 2012-02-08T16:01:02.013 回答
0

只需调用 getResponseCode()。这将启动传输。无论如何,您都必须这样做以确保请求成功,或者找出失败的原因。

于 2010-12-22T23:13:19.560 回答