Cause
As a full-time phper occasional guest in the Androider, a recent company project requires Android clients (major image effects processing and upload), on their own guest in the Androider.
Previous experience in Android development so this is quite handy, almost everything directly github in the use of the change, but in the processing picture upload when the choice of xutils this
Open Source Tool class, it is really easy to use, very convenient, such as the following code can be uploaded:
Requestparams params = Newrequestparams ();
Params.addbodyparameter ("file", file);
Httputils httputils = Newhttputils ();
Httputils.send (HttpRequest.HttpMethod.POST, Upload_url, params, newrequestcallback<string> () {
@Override
Upload Failure handling method
Publicvoidonfailure (HttpException arg0, String msg) {
Alert (msg);
}
@Override
Upload Progress Processing
Publicvoidonloading (Longtotal,longcurrent,
booleanisuploading) {
if (isuploading) {
LOG.I (Log_name, "upload:" + current + "/" + total);
}
}
@Override
Upload successful processing
Publicvoidonsuccess (responseinfo<string> responseinfo) {
alert (Responseinfo.result);
LOG.I (Log_name, Responseinfo.result);
}
});
You can see it is more convenient to use, if you write or more trouble. But the most annoying is not the use of methods, but as a receiver of PHP is not receive uploaded files, and finally confirmed
Not only PHP C # also have problems, online search for a lot of people have problems, but there is no solution, it seems only their own hands to solve the
Problem analysis
Now that you want to solve the problem, you need to analyze where the bug might be, and since it's HTTP upload, then we need to know how the file is handled in PHP in the HTTP protocol, directly in the official document
You'll find
PHP can accept any uploaded files from browsers that meet the RFC-1867 standard (including Netscape Navigator 3 and later, patched Microsoft Internet Explorer 3 or later).
This is the explanation given in the PHP official document that PHP follows the RFC-1867 standard when handling uploads, then we'll see what is RFC-1867.
Here I give a RFC-1867 description of the document address RFC-1867 description, too long will not be placed here to take a look at the core focus:
# The client might send back to the following data use POST method:
Content-type:multipart/form-data, boundary=aab03x
--aab03x
Content-disposition:form-data; Name= "Field1"
Joe Blow
--aab03x
Content-disposition:form-data; Name= "Pics"; Filename= "File1.txt"
Content-type:text/plain
... contents of file1.txt ...
--aab03x--
The popular point here, RFC-1867 through the HTTP protocol to transfer a specific format to upload files, such as we upload a file named Hello.txt text to the server, then the HTTP format of the request should be the following:
post/up.phphttp/1.1
Host:creturn.com
content-length:294
Content-type:multipart/form-data, boundary=aab03x
--aab03x
Content-disposition:form-data; Name= "File"; Filename= "Hello.txt"
Content-type:text/plain
Hello
--aab03x--
Here the HTTP header protocol is not written in complete only to illustrate the format of the problem write. In these descriptive information
The first Content-type (HTTP header description information) value Multipart/form-data is to tell the server this sent data is the upload file data, boundary is to tell the server file data between the partition designator is aab03x
Split multiple files with-aab03x in the HTTP body data, and the description below each delimiter is described as an upload file
The "-" symbol is required to mark the end of the send
If these three points are not a problem then can upload correctly, of course, the second instance is certainly not successful because the HTTP header protocol description information is short and not fight (such as length)
Resolution process
Since the above has analyzed the problem, also know that as long as the sending process is in accordance with the RFC-1867 standard to send so at least PHP is able to receive uploaded files, then we have to solve is if the judge
or check to see if the RFC-1867 standard is followed during xutils send files
So how do I see if xutils sent the correct data format? There are two options, one is to use the Agent tool grab package, another option is to grab the bag directly
Here is to say directly grab bag, agent grab bag can Google a lot of.
PC set up a wireless hotspot to share to the mobile phone, so that all the data go through the computer, will not use the PC to share the hot Google a lot of, or to lazy buy a legendary mini WiFi will do
Grab Kit tool window recommend smartsniff, Linux or OS X directly tcpdump.
First write a simple app to put on the phone here to give the upload code:
String upload_url = "http://www.creturn.com/up.php";
File File = NewFile (Environment.getexternalstoragedirectory (), "hello.txt");
Requestparams params = Newrequestparams ();
Params.addbodyparameter ("file", file);
Httputils httputils = Newhttputils ();
Httputils.send (HttpRequest.HttpMethod.POST, Upload_url, params, newrequestcallback<string> () {
@ Override
//Upload failure handling method
Publicvoidonfailure (HttpException arg0, String msg) {
alert (msg);
}
@Override
//Upload Progress Processing
publicvoidonloading (longtotal,longcurrent,
booleanisuploading) {
if ( isuploading) {
log.i (log_name, "upload: + current +"/"+ total);
}
@Override
// Upload successfully handle
publicvoidonsuccess (responseinfo<string> responseinfo) {
alert (responseinfo.result);
&NBSP;LOG.I (Log_name, Responseinfo.result);
}
});
The code above is to upload the Hello.txt file of the SDcard root directory to Upload_url, so put a hello.txt file inside the sdcard root directory to write the contents of a random point
PHP server side directly to print uploaded file information on the line, the code is very simple:
<?php
Print_r ($_files);
?>
If the upload is successful will be feedback upload file information, write a good app installed to the mobile phone to connect WiFi and then grab the bag on the PC, I used here is a smart sniffer
Grab Bag
Turn on Smart sniffer
Select menu Options-> Capture Options
Choose your WiFi-sharing network card
OK click Start Grab Bag
In the mobile phone app upload file can be seen in the grab tool already has the corresponding HTTP data, grab tool will crawl all traffic so if there are other packet interference can also
Set the appropriate filtering rules, this is not explained here Google will be able to find
Look at the bag we caught:
The graph can see our uploaded HTTP packet information, but obviously the feedback message is not uploaded successfully.
So, how do we analyze this next? How to troubleshoot problems? Many people should be able to think that if there is a correct reference is not easy to analyze the source of the problem?
So we are building an HTML file in the browser also upload sdcard inside the hello.txt file, HTML content as follows:
<body>
<formaction= "http://www.creturn.com/up.php" method= "post" enctype= "Multipart/form-data" >
<labelfor= "File" >Filename:</label>
<inputtype= "File" name= "file" id= "file"/>
<br/>
<inputtype= "Submit" name= "submit" value= "Submit"/>
</form>
</body>
Grab the bag in the same way and see what the correct package content is:
post/up.phphttp/1.1
Host:www.creturn.com
Connection:keep-alive
content-length:294
Cache-control:max-age=0
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
origin:http://222.73.234.196
user-agent:mozilla/5.0 (Windows NT 6.1; WOW64) applewebkit/537.36 (khtml, like Gecko) chrome/31.0.1650.63 safari/537.36
Content-type:multipart/form-data; boundary=----WEBKITFORMBOUNDARYIEXDOW8E2EZYCIDK
Referer:http://222.73.234.196/up.html
Donttrackmehere:gzip,deflate,sdch
accept-language:zh-cn,zh;q=0.8
------WEBKITFORMBOUNDARYIEXDOW8E2EZYCIDK
Content-disposition:form-data; Name= "File"; Filename= "Hello.txt"
Content-type:text/plain
Hello Upload
------WEBKITFORMBOUNDARYIEXDOW8E2EZYCIDK
Content-disposition:form-data; Name= "Submit"
Submit
------webkitformboundaryiexdow8e2ezycidk--
You can see the processing HTTP header description information and the package body inside a more submit, almost the same
Before I said the upload process of several points, and then we found that Content-type description information more than a charset character encoding description information
Then the test must be done to remove different places, and then play back to the package to see if the success
Baohuifang refers to packet packets being sent again
There are two ways to replay packets, a direct modification of the Xutils source code to upload. Here's a simple method window with Telnet, with Telnet linked server 80 port
Send data manually
Note: Windows7 default does not have to be installed in the Control Panel-> programs and features-> turn on or off Windows features
How do I send it manually? According to our previous idea to remove CharSet description information and then manually send, then remove the charset information after the package contents into Notepad:
post/up.phphttp/1.1
user-agent:mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) applewebkit/537.73.11 (khtml, like Gecko) version/7.0.1 safari/537.73.11
content-length:233
Content-type:multipart/form-data; Boundary=6wygreva02r_uy4ejp31ecijtsblztrv
Host:wwwcreturn.com
Connection:keep-alive
Donttrackmehere:gzip
--6wygreva02r_uy4ejp31ecijtsblztrv
Content-disposition:form-data; Name= "File"; Filename= "Hello.txt"
Content-type:application/octet-stream
Content-transfer-encoding:binary
Hello Upload
--6wygreva02r_uy4ejp31ecijtsblztrv--
Open cmd and enter Telnet www.creturn.com 80 and paste it in to see the effect.
In order to verify our only line can add to and remove CharSet to compare to see if it is added after the upload file is not received information.
In fact, according to the HTTP protocol is theoretically added charset should not affect the upload, but the result of this problem is indeed due to charset caused.
Then it's easy to find the source of the solution on the line, in the source code inside the search boundary, find the place according to the author's method of comment out of the Add charset code:
Protectedstringgeneratecontenttype (
finalstring boundary,
Finalcharset charset) {
stringbuilder Buffer = Newstringbuilder ();
buffer.append ("multipart/" + Multipartsubtype + "; boundary=");
buffer.append (boundary);
//This is the code that needs to be commented out
/*if (charset!= null) {
buffer.append ("; Charset= ");
buffer.append (Charset.name ());
}*/
returnbuffer.tostring ();
}