很少,在将GZIP压缩的字符串发送到MySQL服务器并返回之后,我得到CRC不匹配。以下是数据的流动方式。
我的Android应用中有一个大字符串。我使用
将其压缩为字节数组public synchronized static byte[] compress(String str) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream(str.length());
GZIPOutputStream gz_out = new GZIPOutputStream(os);
gz_out.write(str.getBytes());
gz_out.finish();
gz_out.flush();
gz_out.close();
os.flush();
os.close();
byte[] test = os.toByteArray();
String check = decompress(test, false); // making sure CRC Mismatch doesn't occur here.
if (check == null) {
return compress(str);
}
return test;
}
public synchronized static String decompress(byte[] compressed, boolean throwException) {
try {
final int BUFFER_SIZE = 32;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
StringBuilder string = new StringBuilder();
byte[] data = new byte[BUFFER_SIZE];
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
string.append(new String(data, 0, bytesRead));
}
gis.close();
is.close();
return string.toString();
} catch (IOException e) {
if (throwException)
throw new RuntimeException("Failed to decompress GZIP.", e);
else {
Log.e(log_tag, "Failed to decompress GZIP.", e);
return null;
}
}
}
我将它发送到我的服务器:
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("data", data);
InputStream is = null;
try {
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 20000);
HttpConnectionParams.setSoTimeout(httpParams, 20000);
HttpClient httpclient = new DefaultHttpClient(httpParams);
HttpPost httppost = new HttpPost(SERVER_ADDRESS + "sendData.php");
httppost.setEntity(builder.build());
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (Exception e) {
Log.e("FriendlyFire", "Error in http connection", e);
return null;
}
// Then read response...
sendData.php如下所示:
//I read the bytes into a variable using
$data = $_POST['data'];
//I create a MySQL connection using
$conn = new mysqli(...);
//I prepare a statement using
$stmt = $conn->prepare("CALL database.saveData(?);");
//I attach the data using
$stmt->bind_param('s', $data);
//I execute the statement using
$stmt->execute();
//I close the statement using
$stmt->close();
//I close the connection using
$conn->close();
MySQL程序如下所示:
database.saveData(data BLOB)
BEGIN
INSERT INTO Table (columnName) VALUES (data);
END
要将数据下载到我的Android应用,请执行以下操作:
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
HttpConnectionParams.setSoTimeout(httpParams, 10000);
HttpClient httpclient = new DefaultHttpClient(httpParams);
HttpPost httppost = new HttpPost(SERVER_ADDRESS + "getData.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
byte[] data = EntityUtils.toByteArray(entity);
getData.php看起来像这样:
$conn = mysqli_connect(...);
$db = mysqli_select_db($conn, "database");
$result = mysqli_query($conn, "CALL database.getData()");
$num_results = mysqli_num_rows($result);
if ($num_results > 0){
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC))
{
$filedata = $row['columnName'];
header("Content-length: ".strlen($filedata));
header("Content-disposition: download; filename=data.bin");
echo $filedata;
}
} else {
echo "EMPTY";
}
getData()过程如下所示:
database.getData()
BEGIN
SELECT columnName FROM Table LIMIT 1;
END
就像我说的那样,在尝试解压缩从服务器读取的内容之后,我偶尔会遇到CRC不匹配错误。我怀疑问题出在我的PHP代码中,但它可能在我的Android代码中。我有理由相信SQL程序没问题。
GZIP表示99.9%的问题是由于传输是用ASCII而不是二进制完成的。我已尽力将数据保存为二进制,但我必须遗漏一些东西。就像我说的,我怀疑我的PHP代码,特别是上传代码。我直接从MySQL服务器下载了BLOB,它也给出了CRC不匹配错误。
我已经尝试使用bind_param('b',$ data)准备mysqli语句,但SQL表中的结果数据是0字节,我在使用'b'参数类型时找不到多少。我应该使用_FILES而不是_POST吗?这甚至会有所作为吗?
编辑:我对Android和PHP上传代码做了进一步的更改:
在Android中我改变了
builder.addBinaryBody("data", data);
到
builder.addBinaryBody("data", data, Content.DEFAULT_BINARY, "data.bin");
PHP改变了:
$filename = $_FILES['data']['tmp_name'];
//I create a MySQL connection using
$conn = new mysqli(...);
//I prepare a statement using
$stmt = $conn->prepare("CALL database.saveData(?);");
//I attach the data using
$stmt->bind_param('b', $data);
$fp = fopen($filename, "r");
while ($data = fread($fp, 1024)) {
$stmt2->send_long_data(0, $data);
}
//I execute the statement using
$stmt->execute();
//I close the statement using
$stmt->close();
//I close the connection using
$conn->close();
因此,使用'b'参数成功将数据发送到MySQL服务器。服务器中的结果数据不为空。我已经下载了数据并成功地对其进行了一次枪杀。如果我完全停止了CRC不匹配,我会将其标记为正确的答案。
答案 0 :(得分:0)
在Android中我改变了
builder.addBinaryBody("data", data);
到
builder.addBinaryBody("data", data, Content.DEFAULT_BINARY, "data.bin");
前者似乎将数据放在_POST数组中,而后者将数据放入_FILES数组。
PHP改变了:
$filename = $_FILES['data']['tmp_name'];
//I create a MySQL connection using
$conn = new mysqli(...);
//I prepare a statement using
$stmt = $conn->prepare("CALL database.saveData(?);");
//I attach the data using
$stmt->bind_param('b', $data);
$fp = fopen($filename, "r");
while ($data = fread($fp, 1024)) {
$stmt2->send_long_data(0, $data);
}
//I execute the statement using
$stmt->execute();
//I close the statement using
$stmt->close();
//I close the connection using
$conn->close();
因此,使用'b'参数成功将数据发送到MySQL服务器。服务器中的结果数据不为空。我已经下载了数据并成功地对其进行了一次枪杀。
我自从没有出现CRC不匹配错误。
希望我已经解释得这么好了。