我在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
答案 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上始终失败。所以我将列出最终有效的代码更改。
while (responseDataInputStream.read(buffer) != -1)