Heroku不处理来自Android的多部分表单POST

时间:2015-05-06 07:04:32

标签: android heroku

我在rails 4上有一个API,它以文件上传的形式接受HTTP请求。在Localhost上一切正常,但在Heroku上,POST请求似乎没有做任何事情。

这就是我的Android POST请求:

public static byte[] postData(String operation, byte[] binaryData) {
String urlString = baseUrl + "/" + operation;
    String boundary = "uahbkjqtjgecuaoehuaebkjahj";

    byte[] postData = null;
    URLConnection urlConnection;
    DataInputStream responseDataInputStream;

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    StringBuffer startBuffer = new StringBuffer("--").append(boundary).append("\r\n");
    startBuffer.append("Content-Disposition: form-data; name=\"data\"; ").append("filename=\"data.dat\"\r\n");
    startBuffer.append("Content-Type: application/octet-stream\r\n\r\n");
    StringBuffer endBuffer = new StringBuffer("\r\n--").append(boundary).append("--\r\n");

    String startRequestData = startBuffer.toString();
    String endRequestData = endBuffer.toString();
    try {
        URL url = new URL(urlString);
        urlConnection = url.openConnection();
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(true);
        urlConnection.setUseCaches(false);

        urlConnection.setConnectTimeout(5000); //5 seconds
        urlConnection.setReadTimeout(5000);//5 seconds

        urlConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
        urlConnection.connect();
        DataOutputStream _request = new DataOutputStream(urlConnection.getOutputStream());

        // Write the start portion of the request
        byteArrayOutputStream.write(startRequestData.getBytes());
        postData = byteArrayOutputStream.toByteArray();
        _request.write(postData);

        // Write the Binary Packet
        _request.write(binaryData);

        // Write the end portion of the request
        byteArrayOutputStream.reset();
        byteArrayOutputStream.write(endRequestData.getBytes());
        postData = byteArrayOutputStream.toByteArray();
        _request.write(postData);

        _request.flush();
        _request.close();

        // Read in the response bytes
        InputStream is = urlConnection.getInputStream();
        responseDataInputStream = new DataInputStream(is);
        byteArrayOutputStream.reset();
        byte[] buffer = new byte[responseDataInputStream.available()];

        while (responseDataInputStream.read(buffer) != -1) {
            byteArrayOutputStream.write(buffer);
            buffer = new byte[responseDataInputStream.available()];
        }

        byte[] responseData = byteArrayOutputStream.toByteArray();

        return responseData;

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (SocketTimeoutException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new byte[0];

}

我的导轨控制器

skip_before_filter  :verify_authenticity_token
respond_to :raw
before_filter :read_file

def read_file
 data = params[:data].tempfile
 data_compressed = ''
 File.open(data, 'r') do |file|
   file.each do |line|
    data_compressed.concat(line)
   end
 end

 @json_data = Zlib::Inflate.inflate(data_compressed)
end

def an_action
 #processing stuff
 response = Zlib::Deflate.deflate(j_response)
 send_data @json_response.to_s
end

Heroku日志显示控制器操作已被命中,但日志中没有其他操作

2015-05-05T22:39:29.860161+00:00 heroku[router]: at=info method=POST path="/api/login" host=[my app].herokuapp.com request_id=9d9c91b1-2ce2-4db5-9b54-3dea0322e211 fwd="197.237.24.179" dyno=web.1 connect=4ms service=12ms status=500 bytes=1683
2015-05-05T22:40:40.952219+00:00 heroku[router]: at=info method=POST path="/api/signup" host=[my app].herokuapp.com request_id=4adac44c-66e6-4001-a568-8eb913176091 fwd="197.237.24.179" dyno=web.1 connect=4ms service=8ms status=500 bytes=1683

1 个答案:

答案 0 :(得分:0)

在将我的焦点从Heroku转移到Android代码之后,我发现在代码的这一部分有一个无限循环:

while (responseDataInputStream.read(buffer) != -1) {
        byteArrayOutputStream.write(buffer);
        buffer = new byte[responseDataInputStream.available()];
    }

当没有任何内容可读时,返回值为0而不是-1。所以我把它更新为:

while (responseDataInputStream.read(buffer) > 0) {
            byteArrayOutputStream.write(buffer);
            buffer = new byte[responseDataInputStream.available()];
        }

奇怪的是,在localhost上,第一段代码可以工作,它也可以用于生产。文档指出,如果到达流末尾DataInputStream.read(),则返回-1。也许那是另一天的讨论,现在我正在使用第二段代码。

修改

这个问题困扰了我好几个星期,经过大量的谷歌搜索和调整代码后,我想指出这种方法是错误的路线。该代码适用于WIFI连接但在3G上始终失败。所以我将列出最终有效的代码更改。

  1. 使用HttpURLConnection而不是URLConnection。原因here
  2. 将Connect和Read超时的大小分别从5000增加到30000和120000。
  3. 将while条件还原为while (responseDataInputStream.read(buffer) != -1)