为了账号安全,请及时绑定邮箱和手机立即绑定

POST 文件(作为二进制流)使用 java.net.HttpURLConnection 作为参数

POST 文件(作为二进制流)使用 java.net.HttpURLConnection 作为参数

饮歌长啸 2023-02-23 17:29:53
我正在尝试使用 java.net.HttpURLConnection 将文件上传 (POST) 到端点,但我一直收到 http 代码 400(错误请求)。我参考了在 android API 23 中使用 HttpURLConnection 将文件和参数发送到服务器但问题是我需要将此文件作为请求正文参数 (file=) 发送。注意:这些文件只有很小的尺寸(4-5mb)所以我完全在内存中阅读它。对应的 curl 请求为:curl -X POST "API" -H "Content-Type: multipart/form-data" -F "file="我正在使用的代码摘录:    Proxy webproxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("                                 <proxy host>", <proxy_port>));    HttpURLConnection http_conn = (HttpURLConnection)                                      url.openConnection(webproxy);    String authorization = getAuthorization(access_token);    http_conn.setRequestMethod("POST");    http_conn.setRequestProperty("Accept-Charset", "UTF-8");            http_conn.setRequestProperty("Authorization", authorization);    http_conn.setRequestProperty("Connection", "Keep-Alive");    http_conn.setRequestProperty("Content-Type", "multipart/form-data);      http_conn.setDoOutput(true);    http_conn.setDoInput(true);    DataOutputStream outputStream;    outputStream = new DataOutputStream(http_conn.getOutputStream());    File file_obj = new File(this.file);                                    byte[] allBytes = new byte[(int) file_obj.length()];    FileInputStream fileInputStream = new FileInputStream(file_obj);                    outputStream.write("file=".getBytes("UTF-8")); <---Trying to add file param here    fileInputStream.read(allBytes);    outputStream.write(allBytes);发布我刚刚使用下面的代码读取响应(适用于不同的 GET 请求):    InputStream inputStream = http_conn.getInputStream();                    BufferedReader bufferedReader = new BufferedReader(new     InputStreamReader(inputStream));    String line = "";                while ((line = bufferedReader.readLine()) != null) {        data = data + line;                    }注意:我很少使用 java,对它不是很熟悉,所以请在您的回复中进行描述。
查看完整描述

2 回答

?
交互式爱情

TA贡献1712条经验 获得超3个赞

当查看您的 curl 命令行时,它表明该文件需要作为请求发送multipart/form-data。这实际上是一种在需要时格式化数据的复杂方法。

您需要发送的格式示例是:

标头:

Content-Type: multipart/form-data; boundary=AaB03x

身体:

--AaB03x
Content-Disposition: form-data; name="files";
 filename="file1.txt"Content-Type: text/plain

... contents of file1.txt ...
--AaB03x--

目前,您的代码正在将文件作为 POST/GET 格式的请求发送,这不起作用,因为后端不希望这样做。

为了解决这个问题,我们需要将源文件格式化成后端需要的格式,一旦知道“boundary”头选项只是一个随机生成的值,发送请求就变得容易多了。

String boundary = "MY_AWESOME_BOUNDARY"

http_conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);  


try(DataOutputStream outputStream = new DataOutputStream(http_conn.getOutputStream())) {

    File file_obj = new File(this.file);                      


    // Write form-data header   

    outputStream.write(("--" + boundary + "\r\n").getBytes("UTF-8"));

    outputStream.write(("Content-Disposition: form-data; name=\"file\"; filename=\"file1.txt\"\r\n").getBytes("UTF-8"));

    outputStream.write(("Content-Type: text/plain\r\n").getBytes("UTF-8"));

    outputStream.write(("\r\n").getBytes("UTF-8"));

    // Write form-data body

    Files.copy(file_obj.toPath(), outputStream)

    // Write form-data "end"

    outputStream.write(("--" + boundary + "--\r\n").getBytes("UTF-8"));

}

// Read backend response here

try(InputStream inputStream = http_conn.getInputStream()) {           

    BufferedReader bufferedReader = new BufferedReader(new 

    InputStreamReader(inputStream));

    StringBuilder lines = new StringBuilder(); // StringBuilder is faster for concatination than appending strings           

    while ((line = bufferedReader.readLine()) != null) {

        lines.append(line);                

    }

    System.out.println(lines);

}

请注意,我使用了“try-with-resource”块,这些块确保在您使用完它们后关闭和处置任何外部资源,与内存量相比,通常操作系统的开放资源限制非常低你的程序有,所以发生的是你的程序可能会出现奇怪的错误,这些错误只会在运行一段时间后或用户在你的应用程序中执行某些操作时发生


查看完整回答
反对 回复 2023-02-23
?
波斯汪

TA贡献1811条经验 获得超4个赞

以上对我没有用,所以我切换到不同的包(okhttp3),这是对我有用的:


    File file_obj = new File(this.file); 

    String authorization = "my authorization string";

    Proxy webproxy = new Proxy(Proxy.Type.HTTP, new 

          InetSocketAddress("proxy", <port>));


    OkHttpClient client = new OkHttpClient.Builder().proxy(webproxy).build();      


    RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("file", "filename",

        RequestBody.create(MediaType.parse("application/octet-stream"), file_obj)).build();


    Request request = new Request.Builder().header("Authorization", authorization).url(this.url).post(requestBody).build();


    try (Response response = client.newCall(request).execute()){

        if(!response.isSuccessful()) return "NA";

        return (response.body().string());

    }


查看完整回答
反对 回复 2023-02-23
  • 2 回答
  • 0 关注
  • 310 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信