【问题标题】:POST file (as binary stream) using java.net.HttpURLConnection as a param file=<file binary stream>POST 文件(作为二进制流)使用 java.net.HttpURLConnection 作为参数 file=<file binary stream>
【发布时间】:2019-07-02 06:00:39
【问题描述】:

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

我参考了Send File And Parameters To Server With HttpURLConnection in android API 23

但问题是我需要将此文件作为请求正文参数 (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,对它不是很熟悉,所以请在您的回复中进行描述。

【问题讨论】:

    标签: java multipartform-data httpurlconnection sophoslabs-intelix


    【解决方案1】:

    查看您的 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 格式的请求发送,这不起作用,因为后端没有预料到。

    为了解决这个问题,我们需要将源文件格式化成后端需要的格式,而一旦知道“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”块,这些块确保在您完成使用它们时关闭并处置任何外部资源,通常操作系统的开放资源限制非常低,与你的程序有多少内存,所以你的程序可能会出现奇怪的错误,这些错误只有在运行一段时间后或用户在你的应用程序中执行某些操作时才会发生

    【讨论】:

      【解决方案2】:

      以上对我没有用,所以我切换到不同的包(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());
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-09
        • 2010-10-10
        • 2013-03-22
        • 1970-01-01
        • 1970-01-01
        • 2014-01-29
        相关资源
        最近更新 更多