Php Volley库、多部件请求和UTF-8支持
我有个问题。Php Volley库、多部件请求和UTF-8支持,php,android,utf-8,android-volley,persian,Php,Android,Utf 8,Android Volley,Persian,我有个问题。 我写了一个有服务器端和客户端的应用程序。 客户端可以通过应用程序发送包含文本和照片的报告。我使用了截击库;因此,我为名为MultipartRequest的请求创建了一个自定义类。 我的问题是,当我发送一份带有图片和一些英文文本的报告时,程序运行良好。但是当我想用波斯语发送文本时,它不会被发送。 我用Postman测试了我的服务器的PHP类,它们甚至在波斯语中也能正常工作。 如果你能帮助我,我将非常感激。 这是我的主要方法: private void saveReportToSer
我写了一个有服务器端和客户端的应用程序。 客户端可以通过应用程序发送包含文本和照片的报告。我使用了截击库;因此,我为名为MultipartRequest的请求创建了一个自定义类。 我的问题是,当我发送一份带有图片和一些英文文本的报告时,程序运行良好。但是当我想用波斯语发送文本时,它不会被发送。
我用Postman测试了我的服务器的PHP类,它们甚至在波斯语中也能正常工作。
如果你能帮助我,我将非常感激。
这是我的主要方法:
private void saveReportToServer(){
final ProgressDialog ProgressDialog=新建ProgressDialog(上下文);
progressDialog.setMessage(“发送…”);
progressDialog.show();
MultipartRequest MultipartRequest=新的MultipartRequest(Request.Method.POST,AppConfig.URL\u ADD\u report,
新的Response.Listener(){
@凌驾
公共void onResponse(字符串响应){
progressDialog.disclose();
试一试{
JSONObject jObj=新的JSONObject(响应);
如果(!jObj.getBoolean(“错误”)){
//融洽关系成功存储在MySQL中
}否则{
Log.d(标记,jObj.getString(“error_msg”);
//有一些错误
onError();
}
}捕获(JSONException错误){
Log.d(标记,err.toString());
}
}
},
新的Response.ErrorListener(){
@凌驾
公共无效onErrorResponse(截击错误){
Log.d(标记“服务器上的错误-->”+Error.toString());
progressDialog.disclose();
//出错时,将关系存储到SQLite
onError();
}
}
) {
/**
*这里我们传递字符串参数
*/
@凌驾
受保护的映射getParams()引发AuthFailureError{
//发布参数以添加融洽关系url(php)
Map params=新的HashMap();
最后一个字符串subject=_etSubject.getText().toString().trim();
最终字符串位置=_etLocation.getText().toString().trim();
最终字符串描述=_etdescripp.getText().toString().trim();
final HashMap user=db.getUserDetails();
最终字符串email=user.get(“email”);
参数put(“电子邮件”,电子邮件);
参数put(“主体”,主体);
参数put(“位置”,位置);
参数put(“说明”,说明);
返回参数;
}
/**
*在这里,我们通过使用唯一名称重命名图像来传递图像
*/
@凌驾
受保护的映射getByteData()引发AuthFailureError{
Map params=新的HashMap();
long imageName=System.currentTimeMillis();
参数put(“pic”,新数据部分(imageName+“.jpg”,getFileDataFromDrawable(位图));
Log.i(标记,“发送的数据(图像)参数”);
返回参数;
}
};
//将请求添加到请求队列
AppController.getInstance().addToRequestQueue(multipartRequest,tag_req);
}//结束:SaveReportToServer
/**
*该方法将位图作为参数
*此方法将返回给定位图的字节[]数组
*我们将把这个数组发送到服务器
*/
公共字节[]getFileDataFromDrawable(位图){
ByteArrayOutputStream baOutputStream=新建ByteArrayOutputStream();
compress(bitmap.CompressFormat.JPEG,90,baOutputStream);
返回baOutputStream.toByteArray();
}
这里是我的MultipartRequest类:
public类MultipartRequest扩展请求{
专用最终字符串双连字符=“--”;
专用最终字符串lineEnd=“\r\n”;
private final String boundary=“apiclient-”+System.currentTimeMillis();
私人最终回应。监听器;
private final Response.ErrorListener mErrorListener;
私有最终映射mHeaders=newhashmap();
公共多部分请求(int方法、字符串url、,
Response.Listener,Response.ErrorListener ErrorListener){
super(方法、url、errorListener);
this.mListener=侦听器;
this.mErrorListener=errorListener;
}
@凌驾
公共映射getHeaders()引发AuthFailureError{
返回(mHeaders!=null)?mHeaders:super.getHeaders();
}
@凌驾
公共字符串getBodyContentType(){
返回“多部分/表单数据;边界=”+边界;
}
@凌驾
公共字节[]getBody()抛出AuthFailureError{
ByteArrayOutputStream baOutputStream=新建ByteArrayOutputStream();
DataOutputStream dOutputStream=新的DataOutputStream(baOutputStream);
试一试{
//填充文本负载
Map params=getParams();
if(params!=null&¶ms.size()>0){
textParse(dOutputStream,params,getParamsEncoding());
}
//填充数据字节有效负载
映射数据=getByteData();
if(data!=null&&data.size()>0){
数据解析(双输出流,数据);
}
//在文本和文件数据之后关闭多部分表单数据
写字节(两个连字符+边界+两个连字符+行结束);
返回baOutputStream.toByteArray();
}捕获(IOEX异常){
例如printStackTrace();
}
返回null;
}
/**
*自定义方法处理数据负载。
*@返回带有数据字节的地图数据部件标签
*@AuthFailureError
*/
受保护的映射getByteData()引发AuthFailureError{
返回null;
}
@凌驾
受保护的响应parseNetworkResponse(NetworkResponse响应){
试一试{
字符串utf8String=urldecover.decode(urlcodector.e
private void saveRapportToServer() {
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setMessage("Sending...");
progressDialog.show();
MultipartRequest multipartRequest = new MultipartRequest(Request.Method.POST, AppConfig.URL_ADD_RAPPORT,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONObject jObj = new JSONObject(response);
if (!jObj.getBoolean("error")) {
// Rapport successfully stored in MySQL
} else {
Log.d(TAG, jObj.getString("error_msg"));
// there is some error
onError();
}
} catch (JSONException err) {
Log.d(TAG, err.toString());
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Error on server --> " + error.toString());
progressDialog.dismiss();
// on error, storing the rapport to SQLite
onError();
}
}
) {
/**
* Here we are passing our string params
*/
@Override
protected Map<String, String> getParams() throws AuthFailureError {
// Posting params to add rapport url (php)
Map<String, String> params = new HashMap<>();
final String subject = _etSubject.getText().toString().trim();
final String location = _etLocation.getText().toString().trim();
final String description = _etDescrip.getText().toString().trim();
final HashMap<String, String> user = db.getUserDetails();
final String email = user.get("email");
params.put("email", email);
params.put("subject", subject);
params.put("location", location);
params.put("description", description);
return params;
}
/**
* Here we are passing image by renaming it with a unique name
*/
@Override
protected Map<String, DataPart> getByteData() throws AuthFailureError {
Map<String, DataPart> params = new HashMap<>();
long imageName = System.currentTimeMillis();
params.put("pic", new DataPart(imageName + ".jpg", getFileDataFromDrawable(bitmap)));
Log.i(TAG, "Data (image) params sent");
return params;
}
};
// adding request to request queue
AppController.getInstance().addToRequestQueue(multipartRequest, tag_req);
} // END: saveRapportToServer
/**
* The method is taking Bitmap as an argument
* this method will return the byte[] array for the given bitmap
* and we will send this array to the server
*/
public byte[] getFileDataFromDrawable(Bitmap bitmap) {
ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, baOutputStream);
return baOutputStream.toByteArray();
}
public class MultipartRequest extends Request<String> {
private final String twoHyphens = "--";
private final String lineEnd = "\r\n";
private final String boundary = "apiclient-" + System.currentTimeMillis();
private final Response.Listener<String> mListener;
private final Response.ErrorListener mErrorListener;
private final Map<String, String> mHeaders = new HashMap<>();
public MultipartRequest(int method, String url,
Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return (mHeaders != null) ? mHeaders : super.getHeaders();
}
@Override
public String getBodyContentType() {
return "multipart/form-data;boundary=" + boundary;
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
DataOutputStream dOutputStream = new DataOutputStream(baOutputStream);
try {
// populate text payload
Map<String, String> params = getParams();
if(params != null && params.size() > 0) {
textParse(dOutputStream, params, getParamsEncoding());
}
// populate data byte payload
Map<String, DataPart> data = getByteData();
if(data != null && data.size() > 0) {
dataParse(dOutputStream, data);
}
// close multipart form data after text and file data
dOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
return baOutputStream.toByteArray();
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
/**
* Custom method handle data payload.
* @return Map data part label with data byte
* @throws AuthFailureError
*/
protected Map<String, DataPart> getByteData() throws AuthFailureError {
return null;
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
try {
String utf8String = URLDecoder.decode(URLEncoder.encode(new String(response.data), "iso8859-1"), "UTF-8");
return Response.success(utf8String,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception ex) {
return Response.error(new ParseError(ex));
}
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
/**
* Parse string map into data output stream by key and value.
*
* @param dataOutputStream data output stream handle string parsing
* @param params string inputs collection
* @param encoding encode the inputs, default UTF-8
* @throws IOException
*/
private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
try {
for(Map.Entry<String, String> entry : params.entrySet()) {
buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
}
}catch (UnsupportedEncodingException ex) {
throw new RuntimeException("Encoding not supported: " + encoding, ex);
}
}
/**
* Parse data into data output stream.
*
* @param dataOutputStream data output stream handle file attachment
* @param data loop through data
* @throws IOException
*/
private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
for (Map.Entry<String, DataPart> entry : data.entrySet()) {
buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
}
}
/**
* Write string data into header and data output stream.
*
* @param dataOutputStream data output stream handle string parsing
* @param parameterName name of input
* @param parameterValue value of input
* @throws IOException
*/
private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
dataOutputStream.writeBytes(lineEnd);
dataOutputStream.writeBytes(parameterValue + lineEnd);
}
/**
* Write data file into header and data output stream.
*
* @param dataOutputStream data output stream handle data parseing
* @param dataFile data byte as DataPart from collection
* @param inputName name of data input
* @throws IOException
*/
private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
if(dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
}
dataOutputStream.writeBytes(lineEnd);
ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024 * 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while(bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dataOutputStream.writeBytes(lineEnd);
}
class DataPart {
private String fileName;
private byte[] content;
private String type;
public DataPart() { }
public DataPart(String name, byte[] data) {
this.fileName = name;
this.content = data;
}
public String getFileName() {
return fileName;
}
public byte[] getContent() {
return content;
}
public String getType() {
return type;
}
}}
private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
dataOutputStream.writeBytes("Content-Type: text/plain; charset=UTF-8" + lineEnd);
dataOutputStream.writeBytes(lineEnd);
dataOutputStream.writeBytes(parameterValue + lineEnd); }