I'm trying to POST a file to our server using HttpURLConnection on Android, but the getResponseCode call just hangs and never returns. The issue stems from the file being too big for the server, so the server sends back an HTTP error code of 413 (which I can see in the server logs), but on our device, it seems like this is never received. I have the following code in our app:
public FileUploadUtility(URL requestURL, File uploadFile) throws IOException
{
file = uploadFile;
String fileName = uploadFile.getName();
httpURLConnection = (HttpURLConnection) requestURL.openConnection();
httpURLConnection.setUseCaches(false);
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Content-Type", URLConnection.guessContentTypeFromName(fileName));
//httpURLConnection.setRequestProperty("Content-Length", Long.toString(fileSize));
long fileSize = uploadFile.length();
httpURLConnection.setFixedLengthStreamingMode(fileSize);
outputStream = httpURLConnection.getOutputStream();
}
/**
* Completes the request and receives response from the server.
*
* @return a list of Strings as response in case the server returned
* status OK, otherwise an exception is thrown.
* @throws IOException
*/
public String finish(ProgressListener progressListener) throws IOException, HTTPErrorCodeException
{
try (FileInputStream inputStream = new FileInputStream(file))
{
byte[] buffer = new byte[100 * 1024];
int bytesRead;
long fileSize = file.length();
int total = 0;
while ((bytesRead = inputStream.read(buffer)) != -1)
{
outputStream.write(buffer, 0, bytesRead);
total += bytesRead;
if(fileSize > 0)
{
progressListener.fileUploadProgress((float)total / (float)fileSize);
}
}
outputStream.flush();
}
catch (Exception e)
{
e.printStackTrace();
throw new IOException("Error uploading file: " + e.getMessage());
}
String response;
// Checks server's status code first
int status = httpURLConnection.getResponseCode();
if (status == HttpURLConnection.HTTP_OK)
{
try (BufferedReader reader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())))
{
StringBuilder builder = new StringBuilder();
String output;
while ((output = reader.readLine()) != null)
{
builder.append(output);
}
response = builder.toString();
Log.i("Server response body", response);
}
httpURLConnection.disconnect();
httpURLConnection = null;
}
else
{
String serverResponseMessage = httpURLConnection.getResponseMessage();
Log.i("Server Response Message", serverResponseMessage);
try (BufferedReader responseReader = new BufferedReader(new InputStreamReader((httpURLConnection.getInputStream()))))
{
StringBuilder builder = new StringBuilder();
String output;
while ((output = responseReader.readLine()) != null)
{
builder.append(output);
}
Log.i("Server response body", builder.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader((httpURLConnection.getErrorStream()))))
{
StringBuilder builder = new StringBuilder();
String output;
while ((output = errorReader.readLine()) != null)
{
builder.append(output);
}
Log.i("Server error", builder.toString());
}
catch (Exception e)
{
e.printStackTrace();
}
throw new HTTPErrorCodeException(status);
}
return response;
}
Just to reiterate, the issue isn't 'why is the server rejecting the upload', it's why HttpURLConnection doesn't seem to pick up the response code. When breaking into the debugger, it looks like HttpURLConnection is stuck trying to write the output buffer, but the server has already sent the response code before the app finishes writing the output buffer (as the server has rejected the POST based on the header). The server is Nginx forwarding to a Node.JS instance if that helps at all, but as I can see the 413 in the logs, I think it's an issue on the app's side of things. It hangs on the following line:
int status = httpURLConnection.getResponseCode();