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

时间:2019-06-27 13:21:41

标签: java multipartform-data httpurlconnection sophoslabs-intelix

我正在尝试使用java.net.HttpURLConnection将文件上传(POST)到端点,但是我一直收到HTTP代码400(错误请求)。

我提到了Send File And Parameters To Server With HttpURLConnection in android API 23

但是问题是我需要将此文件作为请求正文参数(file =)发送。

注意:文件将只有很小的尺寸(4-5mb),所以我要完全在内存中读取它。

相应的curl请求是:

卷曲-X POST“ API” -H“内容类型: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 个答案:

答案 0 :(得分:4)

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

An example of the format you need to send is:

  

标题:

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格式的请求发送文件,但由于后端不期望这样做,因此此操作不起作用。

要解决此问题,我们需要将源文件格式化为后端所需的格式,并且一旦您知道“边界”标头选项只是一个随机生成的值,发送请求就变得更加容易。

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”块,这些块可确保在使用完所有外部资源后都将其关闭并进行处置,与之相比,通常操作系统的开放资源限制非常低。程序具有的内存量,所以发生的情况是程序可能会产生奇怪的错误,这些错误只会在运行一段时间或用户在应用程序内执行某些操作后才会发生

答案 1 :(得分:1)

以上对我没有用,所以我切换到了其他软件包(okhttp3),这对我有用:

.widthInPx(@w)
{
    width: unit(@w, px);
}

.some-style
{
    .widthInPx(@width);
}