今天碰到一个很奇怪的问题,我在后台用php写好接口,然后在app端进行调用,但是出现一个很奇怪的事情,英文插入到数据库没有问题,但是中午插入就出现“?”的乱码,我刚开始觉得是数据库的字符集的问题,我就把数据库的字符集修改两遍,成为UTF-8,然后反反复复建表,我一直觉得是数据库的问题,然后后面我又觉得是不是我的PHP代码有问题,然后我又调试PHP代码。包括用WEB端进行表单上传,后来好不容易把WEB端调试好了,不出现乱码了,我在app端进行接口的调用,当数据插入到数据库的时候出现乱码,当时我就毛了。咋整的?我用的是Volly框架写的,因为项目本来就不大,还如果用retrofit写的话,投入太多,划不来,因为这个本来就是一个比赛的项目,奖金分开就几百块钱。
然后我就开始查看app端是不是流的转换有问题,一个个排查。后来我就发现问题了,我是在自定义的Requst里面的字符集编码没有设置好,完全就是瞎几把搞,现在贡献源码,我们一个个解析:
public class MultipartRequest extends Request{
private MultipartEntity entity = new MultipartEntity();
private Response.Listener mListener;
private List mFileParts;
private String mFilePartName;
private Map mParams;
/**
* 单个文件+参数 上传
* @param url
* @param listener
* @param errorListener
* @param filePartName
* @param file
* @param params
*/
public MultipartRequest(String url, Response.Listener listener, Response.ErrorListener errorListener,
String filePartName, File file, Map params){
super(Method.POST, url, errorListener);
mFileParts =new ArrayList();
if(file != null && file.exists()){
mFileParts.add(file);
}else{
VolleyLog.e("MultipartRequest---file not found");
}
mFilePartName = filePartName;
mListener = listener;
mParams = params;
buildMultipartEntity();
}
/**
* 多个文件+参数上传
* @param url
* @param listener
* @param errorListener
* @param filePartName
* @param files
* @param params
*/
public MultipartRequest(String url,Response.Listener listener,Response.ErrorListener errorListener
, String filePartName,List files, Map params) {
super(Method.POST, url, errorListener);
mFilePartName = filePartName;
mListener = listener;
mFileParts = files;
mParams = params;
buildMultipartEntity();
}
@Override
protected Response parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed =new String(response.data, HttpHeaderParser.parseCharset(response.headers));
}catch (UnsupportedEncodingException e) {
parsed =new String(response.data); }
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
@Override
protected void deliverResponse(String response) {
mListener.onResponse(response);
}
@Override
public Map getHeaders() throws AuthFailureError {
Map headers =super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers =new HashMap(); }
return headers; }
@Override
public String getBodyContentType() {
return entity.getContentType().getValue(); }
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos =new ByteArrayOutputStream();
try{
entity.writeTo(bos);
}catch (IOException e) {
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
private void buildMultipartEntity() {
if (mFileParts != null && mFileParts.size() > 0) {
for (File file : mFileParts) {
entity.addPart(mFilePartName,new FileBody(file)); }
long l = entity.getContentLength();
try {
if (mParams != null && mParams.size() > 0) {
for (Map.Entry entry : mParams.entrySet()) {
entity.addPart( entry.getKey(),
new StringBody(entry.getValue(), Charset
.forName("UTF-8"))); }
}
}catch (UnsupportedEncodingException e) {
VolleyLog.e("UnsupportedEncodingException");
}
}
}
大家可能都发现了,我这个是多表单的上传,但是,文件的上传和文本是分开的。而且我单独给文本配置的UTF-8的字符集编码:
![](https://img.haomeiwen.com/i6253688/cb093946d4c39345.png)
因此,我在这里也要告诉各位全栈 的工程师,多表单上传,需要注意的事情很多,表单的类型,表单的验证,表单的字符串编码校验,都要一一对应,数据库,后台代码,前端接口的流的推送,如果哪个方面没有对应,就会出现今天的这种情况,很简单的一个问题,调试了很久。
然后我现在也给大家奉献一下我的这个类的用法
public static void createFeed( FeedEntity feed, List files){
final Map params = new HashMap();
params.put("userFrom", feed.getUserFrom()+"");
params.put("userNickname", feed.getUserNickname());
params.put("userIcon", feed.getUserIcon());
params.put("content", feed.getContent());
final Map filemap = new HashMap();
for (File file : files) {
filemap.put("f_file[]", file);
}
String url = Constants.url_feed_create;
MultipartRequest request =new MultipartRequest(url, new Listener() {
@Override
public void onResponse(String response) {
TrendCreateHttpManager.toTrendCreateHttpActionSuccess();
}
},new ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
TrendCreateHttpManager.toTrendCreateHttpActionError();
}
} ,"f_file[]", files, params);
Volley.newRequestQueue(MyApplication.newInstance()).add(request);
}
其实还可以封装的更好,但是因为项目比较紧,所以不能管这么多,先能用再考虑封装,如果有什么不对的地方,希望大家指正!
网友评论