一. 前言

1. 关于本地服务器

我的选择是使用自己的电脑作为服务器。我们的手机该如何才能访问的电脑呢?

首先,我们需要将我们的手机和电脑连接在同一个局域网下,手机开热点给电脑连接也可以。

接着,我们需要在终端输入 ifconfig,回车,找到 inet,后面的一串数字就是我们本机的ip地址(ip地址可能变动),比如我的电脑此时的ip就是:192.168.43.43。

2. 操作本地服务器

1
2
3
4
5
//开启apache:  sudo apachectl start

//重启apache: sudo apachectl restart

//关闭apache: sudo apachectl stop

前往本地服务器的文件夹:/Library/WebServer/Documents,在其中配置我们的后台文件。

我们电脑访问本地服务器的方式是:http://localhost/hello

在手机上我们对应的访问方式是:http://192.168.43.43/hello

3. 实际操作可能出现的问题

程序报错:CLEARTEXT communication to XX not permitted by network security policy

我的第一想法是将 http请求 换成 https请求 ,但是发现就不能在手机上访问我电脑上的服务器了。

百度得到结果:安卓9.0系统出现 CLEARTEXT communication to XX not permitted by network security policy

解决步骤:

1
2
3
4
5
6
7
8
9
10
11
//1.创建 network_config.xml 文件
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

//2.AndroidManifest.xml中配置cleartextTrafficPermitted
<application
****
android:networkSecurityConfig="@xml/network_config"
****>

4. 记得在 AndroidManifest.xml 中配置允许联网的权限

1
2
<!--允许连接网络的权限-->
<uses-permission android:name="android.permission.INTERNET"/>

二. Get请求

1. 配置后台文件

在电脑上的服务器文件夹中创建loginGet.php,填入下面的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?PHP
#获取用户输入的姓名和密码
$name = $_GET["name"];
$pwd = $_GET["password"];

#账号类
$account = array(
"name"=>$name,
"password"=>$pwd,
);

#数组
$result = array(
"account"=>$account,
"id"=>"222017602053039",
"status"=>3,
);

#规定返回类型数据为JSON数据
header('Content-Type:application/json');
echo json_encode($result);
?>

2. 使用Postman查询请求

① 请求头

② 请求体

3. 发送同步Get请求获取数据

① 使用

  • 同步Get请求会阻塞主线程,需要开启子线程调用。
  • 使用GsonFormat插件生成模型类。
  • 使用Gson第三方库解析JSON数据。

② 代码解释

  • client执行newCall方法会得到一个Call对象,表示一个新的网络请求。Call对象的execute方法是同步方法,会阻塞当前线程,其返回Response对象。
  • 通过Response对象的isSuccessful()方法可以判断请求是否成功。
  • 通过Response的headers()方法可以得到响应头Headers对象,可以通过for循环索引遍历所有的响应头的名称和值。可以通过Headers.name(index)方法获取响应头的名称,通过Headers.value(index)方法获取响应头的值。
  • 除了索引遍历,通过Headers.get(headerName)方法也可以获取某个响应头的值,比如通过headers.get(“Content-Type”)获得服务器返回给客户端的数据类型。
  • 但是服务器返回给客户端的响应头中有可能有多个重复名称的响应头,比如在某个请求中,服务器要向客户端设置多个Cookie,那么会写入多个Set-Cookie响应头,且这些Set-Cookie响应头的值是不同的,例如访问百度首页,就有3个Set-Cookie响应头。
  • 为了解决同时获取多个name相同的响应头的值,Headers中提供了一个public List values(String name)方法,该方法会返回一个List对象,所以此处通过Headers对象的values(‘Set-Cookie’)可以获取全部的Cookie信息,如果调用Headers对象的get(‘Set-Cookie’)方法,那么只会获取最后一条Cookie信息。
  • 通过Response对象的body()方法可以得到响应体ResponseBody对象,调用其string()方法可以很方便地将响应体中的数据转换为字符串,该方法会将所有的数据放入到内存之中,所以如果数据超过1M,最好不要调用string()方法以避免占用过多内存,这种情况下可以考虑将数据当做Stream流处理。

③ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public class MainActivity extends AppCompatActivity {
//TAG
public static final String TAG = MainActivity.class.getSimpleName();

//OkHttpClient
private final OkHttpClient client = new OkHttpClient();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

new Thread(new Runnable() {
@Override
public void run() {
syncRequestByGet();
}
}).start();
}

/**
* 同步的Get请求
*/
public void syncRequestByGet(){
//请求
Request.Builder builder = new Request.Builder();
builder.url("http://192.168.43.43/login/loginGet?name=xl&password=0000");
Request request = builder.build();

try {
//请求的响应
Response response = client.newCall(request).execute();

//成功的情况下
if (response.isSuccessful()) {
//读取响应体
ResponseBody body = response.body();
String jsonString = body.string();
//InputStream inputStream = body.byteStream();
//Reader reader = body.charStream();

//转化为Student对象
Gson gson = new Gson();
Student student = gson.fromJson(jsonString, Student.class);

Log.d(TAG,student.toString());
}else {

Log.d(TAG,"响应失败");
}
} catch (IOException e) {
e.printStackTrace();

Log.d(TAG,"IO异常:"+e.getMessage());
}
}
}

//运行结果
Date:Mon, 01 Jun 2020 08:25:24 GMT
Server:Apache/2.4.41 (Unix) PHP/7.3.11
Content-Location:loginGet.php
Vary:negotiate
TCN:choice
X-Powered-By:PHP/7.3.11
Content-Length:77
Keep-Alive:timeout=5, max=100
Connection:Keep-Alive
Content-Type:application/json
Student{account=AccountBean{name='xl', password='0000'}, id='222017602053039', status=3}

4. 发送异步Get请求

① 代码解释

  • 要想异步执行网络请求,需要执行Call对象的enqueue方法,该方法接收一个okhttp3.Callback对象,enqueue方法不会阻塞当前线程,会新开一个工作线程,让实际的网络请求在工作线程中执行。
  • 当异步请求成功后,会回调Callback对象的onResponse方法,在该方法中可以获取Response对象。当异步请求失败或者调用了Call对象的cancel方法时,会回调Callback对象的onFailure方法。onResponse和onFailure这两个方法都是在工作线程中执行的。

② 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class MainActivity extends AppCompatActivity {
//TAG
public static final String TAG = MainActivity.class.getSimpleName();

//OkHttpClient
private final OkHttpClient client = new OkHttpClient();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//异步Get请求
asyncRequestByGet();
}

/**
* 异步的Get请求
*/
public void asyncRequestByGet(){
//请求
Request.Builder builder = new Request.Builder();
builder.url("http://192.168.43.43/login/loginGet?name=xl&password=0000");
Request request = builder.build();

client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG,"响应失败");
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//成功的情况下
if (response.isSuccessful()) {
//读取响应头
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG,headers.name(i)+":"+headers.value(i));
}

//读取响应体
ResponseBody body = response.body();
String jsonString = body.string();
//InputStream inputStream = body.byteStream();
//Reader reader = body.charStream();

//转化为Student对象
Gson gson = new Gson();
Student student = gson.fromJson(jsonString, Student.class);

Log.d(TAG,student.toString());
}else {

Log.d(TAG,"响应失败");
}
}
});
}
}

//运行结果
Date:Mon, 01 Jun 2020 08:25:24 GMT
Server:Apache/2.4.41 (Unix) PHP/7.3.11
Content-Location:loginGet.php
Vary:negotiate
TCN:choice
X-Powered-By:PHP/7.3.11
Content-Length:77
Keep-Alive:timeout=5, max=100
Connection:Keep-Alive
Content-Type:application/json
Student{account=AccountBean{name='xl', password='0000'}, id='222017602053039', status=3}

5. 请求头和响应头

典型的HTTP请求头、响应头都是类似于Map<String, String>,每个name对应一个value值。不过像我们之前提到的,也会存在多个name重复的情况,比如相应结果中就有可能存在多个Set-Cookie响应头,同样的,也可能同时存在多个名称一样的请求头。

响应头的读取,我们在上面发送同步Get请求的时候就已经说过了,那么我们如何设置请求头呢?

一般情况下,我们只需要调用header(name, value)方法就可以设置请求头的name和value,调用该方法会确保整个请求头中不会存在多个名称一样的name。如果想添加多个name相同的请求头,应该调用addHeader(name, value)方法,这样可以添加重复name的请求头,其value可以不同,例如如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private final OkHttpClient client = new OkHttpClient();

public void run() {
Request request = new Request.Builder()
.url("https://api.github.com/repos/square/okhttp/issues")
.header("User-Agent", "OkHttp Headers.java")
.addHeader("Accept", "application/json; q=0.5")
.addHeader("Accept", "application/vnd.github.v3+json")
.build();

Response response = client.newCall(request).execute();

System.out.println("Server: " + response.header("Server"));
System.out.println("Date: " + response.header("Date"));
System.out.println("Vary: " + response.headers("Vary"));
}

上面的代码通过addHeader方法添加了两个Accept请求头,且二者的值不同,这样服务器收到客户端发来的请求后,就知道客户端既支持application/json类型的数据,也支持application/vnd.github.v3+json类型的数据。

三. 发送POST请求获取数据

1. 配置后台文件

在电脑上的服务器文件夹中创建loginGet.php,填入下面的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?PHP
#获取用户输入的姓名和密码
$name = $_POST["name"];
$pwd = $_POST["password"];

#账号类
$account = array(
"name"=>$name,
"password"=>$pwd,
);

#数组
$result = array(
"account"=>$account,
"id"=>"222017602053039",
"status"=>3,
);

#规定返回类型数据为JSON数据
header('Content-Type:application/json');
echo json_encode($result);
?>

2. 使用Postman查询请求

① 请求头

② 请求体

3. 发送POST请求获取数据

① 代码解释

  • POST请求无法向GET请求一样直接在URL后面追加键值对信息。
  • 我们通过在请求的Body中加入form-data类型的信息,达到追加信息的效果。

② 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class MainActivity extends AppCompatActivity {
//TAG
public static final String TAG = MainActivity.class.getSimpleName();

//OkHttpClient
private final OkHttpClient client = new OkHttpClient();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//POST请求
requestByPost();
}

/**
* POST请求获取数据
*/
private void requestByPost(){
//Request.Builder
Request.Builder builder = new Request.Builder();

//构建参数键值对
FormBody formBody = new FormBody.Builder()
.add("username", "xl")
.add("password", "0000")
.build();

//构建Request
builder.url("http://192.168.43.43/login/loginGet");
builder.post(formBody);
Request request = builder.build();

client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG,"响应失败");
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//成功的情况下
if (response.isSuccessful()) {
//读取响应头
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG,headers.name(i)+":"+headers.value(i));
}

//读取响应体
ResponseBody body = response.body();
String jsonString = body.string();
//InputStream inputStream = body.byteStream();
//Reader reader = body.charStream();

//转化为Student对象
Gson gson = new Gson();
Student student = gson.fromJson(jsonString, Student.class);

Log.d(TAG,student.toString());
}else {

Log.d(TAG,"响应失败");
}
}
});
}
}

//运行结果
Date:Mon, 01 Jun 2020 09:09:04 GMT
Server:Apache/2.4.41 (Unix) PHP/7.3.11
X-Powered-By:PHP/7.3.11
Content-Length:77
Keep-Alive:timeout=5, max=100
Connection:Keep-Alive
Content-Type:application/json
Student{account=AccountBean{name='xl', password='0000'}, id='222017602053039', status=3}

4. 用POST发送表单数据

  • Okhttp也提供了MultipartBody类帮助我们完成这个功能。
  • MultipartBody继承自RequestBody,也表示请求体。只不过MultipartBody的内部是由多个part组成的,每个part就单独包含了一个RequestBody请求体,所以可以把MultipartBody看成是一个RequestBody的数组,而且可以分别给每个RequestBody单独设置请求头。
  • MultipartBody一定要设置setType(MultipartBody.FORM)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private static final String IMGUR_CLIENT_ID = "...";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");

private final OkHttpClient client = new OkHttpClient();

public void run() throws Exception {
// Use the imgur image upload API as documented at
// https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "Square Logo")
.addFormDataPart("image", "logo-square.png",
RequestBody.create(MEDIA_TYPE_PNG,
new File("website/static/logo-square.png")))
.build();

Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();

Response response = client.newCall(request).execute();

System.out.println(response.body().string());
}

四. 发送POST请求上传文件并获取数据

1. 配置后台文件

在电脑上的服务器文件夹中创建upLoad文件夹以及它下面的file,img,video文件夹,upLoadFile.php文件,并填入下面的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?PHP
//获取文件
$file = $_FILES["file"];

//获取文件信息
if($file["error"] > 0){

//读取文件出错
echo "Error:".$file["error"]."\n";
}else{

//输出详细信息
echo "上传的文件名:".$file["name"]."\n";
echo "上传的文件类型:".$file["type"]."\n";
echo "上传的文件大小:".($file["size"]/1024)."Kb\n";
echo "临时路径:".$file["tmp_name"]."\n";

//判断文件类型
$type = $file["type"];
$path;
if($type == "image/jpeg" || $type == "image/png"){
//图片
$path = "upLoad/img/";
}else if($type == "video/mp4"){
//视频
$path = "upLoad/video/";
}else if($type == "text/plain"){
//文本
$path = "upLoad/file/";
}
}

$filePath = $path.$file["name"];
//判断文件是否存在

if(file_exists($filePath)){
//存在
echo $file["name"]."已存在";
}else{
//不存在
//将临时文件里面的文件移动到指定目录
move_uploaded_file($file["tmp_name"],$filePath);

echo "文件已保存在:".$filePath;
}
?>

2. 使用Postman查询请求

① 上传文本

② 上传图片

③ 上传视频

3. 关于上传文件类型的 MediaType

4. 代码

① 上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* POST上传文本数据
*/
private void uploadTextToServer(){
//文件类型
final MediaType MEDIA_TYPE = MediaType.parse("text/plain; charset=utf-8");

//获取文本数据流
final InputStream is = getResources().openRawResource(R.raw.test);

//请求体
RequestBody text_request = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return MEDIA_TYPE;
}

@Override
public void writeTo(@NotNull BufferedSink bufferedSink) throws IOException {
bufferedSink.write(getBytesByInputStream(is));
}
};

//构建MultipartBody
MultipartBody.Builder multi_builder = new MultipartBody.Builder();
multi_builder.setType(MultipartBody.FORM);
multi_builder.addFormDataPart("file","test.txt",text_request);
RequestBody requestBody = multi_builder.build();

//构建Request
Request.Builder builder = new Request.Builder();
builder.url("http://192.168.43.43/upLoadFile");
builder.post(requestBody);
Request request = builder.build();

client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG,"响应失败");
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//成功的情况下
if (response.isSuccessful()) {
//读取响应头
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG,headers.name(i)+":"+headers.value(i));
}

//读取响应体
ResponseBody body = response.body();
String jsonString = body.string();
//InputStream inputStream = body.byteStream();
//Reader reader = body.charStream();

Log.d(TAG,jsonString);
}else {

Log.d(TAG,"响应失败");
}
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//运行结果
Date:Mon, 01 Jun 2020 11:35:06 GMT
Server:Apache/2.4.41 (Unix) PHP/7.3.11
X-Powered-By:PHP/7.3.11
Content-Length:173
Keep-Alive:timeout=5, max=100
Connection:Keep-Alive
Content-Type:text/html; charset=UTF-8

上传的文件名:test.txt
上传的文件类型:text/plain
上传的文件大小:0.046875Kb
临时路径:/private/var/tmp/phplJlVE7
文件已保存在:upLoad/file/test.txt

② 上传图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* POST上传图片数据
*/
private void uploadPictureToServer(){
//文件类型
final MediaType MEDIA_TYPE = MediaType.parse("image/png");

//获取文本数据流
final InputStream is = getResources().openRawResource(R.raw.test_picture);

//请求体
RequestBody picture_request = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return MEDIA_TYPE;
}

@Override
public void writeTo(@NotNull BufferedSink bufferedSink) throws IOException {
bufferedSink.write(getBytesByInputStream(is));
}
};

//构建MultipartBody
MultipartBody.Builder multi_builder = new MultipartBody.Builder();
multi_builder.setType(MultipartBody.FORM);
multi_builder.addFormDataPart("file","test.png",picture_request);
RequestBody requestBody = multi_builder.build();

//构建Request
Request.Builder builder = new Request.Builder();
builder.url("http://192.168.43.43/upLoadFile");
builder.post(requestBody);
Request request = builder.build();

client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG,"响应失败");
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//成功的情况下
if (response.isSuccessful()) {
//读取响应头
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG,headers.name(i)+":"+headers.value(i));
}

//读取响应体
ResponseBody body = response.body();
String jsonString = body.string();
//InputStream inputStream = body.byteStream();
//Reader reader = body.charStream();

Log.d(TAG,jsonString);
}else {

Log.d(TAG,"响应失败");
}
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//运行结果
Date:Mon, 01 Jun 2020 12:49:54 GMT
Server:Apache/2.4.41 (Unix) PHP/7.3.11
X-Powered-By:PHP/7.3.11
Content-Length:177
Keep-Alive:timeout=5, max=100
Connection:Keep-Alive
Content-Type:text/html; charset=UTF-8

上传的文件名:test.png
上传的文件类型:image/png
上传的文件大小:670.1064453125Kb
临时路径:/private/var/tmp/phpAblC1W
文件已保存在:upLoad/img/test.png

③ 上传视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
* POST上传视频数据
*/
private void uploadMovieToServer(){
//文件类型
final MediaType MEDIA_TYPE = MediaType.parse("video/mp4; charset=utf-8");

//获取文本数据流
final InputStream is = getResources().openRawResource(R.raw.test_movie);

//请求体
RequestBody movie_request = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return MEDIA_TYPE;
}

@Override
public void writeTo(@NotNull BufferedSink bufferedSink) throws IOException {
bufferedSink.write(getBytesByInputStream(is));
}
};

//构建MultipartBody
MultipartBody.Builder multi_builder = new MultipartBody.Builder();
multi_builder.setType(MultipartBody.FORM);
multi_builder.addFormDataPart("file","test.mp4",movie_request);
RequestBody requestBody = multi_builder.build();

//构建Request
Request.Builder builder = new Request.Builder();
builder.url("http://192.168.43.43/upLoadFile");
builder.post(requestBody);
Request request = builder.build();

client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG,"响应失败");
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//成功的情况下
if (response.isSuccessful()) {
//读取响应头
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG,headers.name(i)+":"+headers.value(i));
}

//读取响应体
ResponseBody body = response.body();
String jsonString = body.string();
//InputStream inputStream = body.byteStream();
//Reader reader = body.charStream();

Log.d(TAG,jsonString);
}else {

Log.d(TAG,"响应失败");
}
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//运行结果
Date:Tue, 02 Jun 2020 02:13:29 GMT
Server:Apache/2.4.41 (Unix) PHP/7.3.11
X-Powered-By:PHP/7.3.11
Content-Length:180
Keep-Alive:timeout=5, max=100
Connection:Keep-Alive
Content-Type:text/html; charset=UTF-8

上传的文件名:test.mp4
上传的文件类型:video/mp4
上传的文件大小:20221.448242188Kb
临时路径:/private/var/tmp/phpI5C1uB
文件已保存在:upLoad/video/test.mp4

④ 辅助函数:将输入流->字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 将输入流->字符串
* @param is
* @return
*/
private byte[] getBytesByInputStream(InputStream is) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();

byte[] data = new byte[1024];
int len;
try {
//一直读取
while ((len = is.read(data)) != -1){
bos.write(data,0,len);
}

bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}

return bos.toByteArray();
}

5. 关于上传视频的一点小问题

① Error:1 错误

② PHP上传错误类型

假设文件上传字段的名称file,则$_FILES['file']['error']有以下几种错误类型:

  • UPLOAD_ERR_OK:其值为 0,没有错误发生,文件上传成功。
  • UPLOAD_ERR_INI_SIZE:其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize选项限制的值。
  • UPLOAD_ERR_FORM_SIZE:其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
  • UPLOAD_ERR_PARTIAL:其值为 3,文件只有部分被上传。
  • UPLOAD_ERR_NO_FILE:其值为 4,没有文件被上传。
  • UPLOAD_ERR_NO_TMP_DIR:其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
  • UPLOAD_ERR_CANT_WRITE:其值为 7,文件写入失败。PHP 5.1.0 引进。

③ 改正方式

修改:php.ini 中 upload_max_filesize 选项限制的值。

问题1:Mac OS X中没有默认的php.ini文件

使用对应的模版文件php.ini.default,修改upload_max_filesize,然后执行以下的拷贝命令即可。

1
sudo cp /private/etc/php.ini.default /private/etc/php.ini  

问题2:仍然不成功的情况

php默认的 post_max_size 为 2M。如果 POST 数据尺寸大于 post_max_size,页面不会给出提醒,文件也上传失败 。

按照问题1的方式修改 post_max_size。

五. 发送GET请求下载图片

1. 使用Postman查询请求

2. 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* GET请求下载图片
*/
private void downloadPicture(){
//请求
Request.Builder builder = new Request.Builder();
builder.url("http://192.168.43.43/upLoad/img/test.png");
Request request = builder.build();

client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
Log.d(TAG,"响应失败");
}

@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
//成功的情况下
if (response.isSuccessful()) {
//读取响应头
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG,headers.name(i)+":"+headers.value(i));
}

//读取响应体
ResponseBody body = response.body();
//String jsonString = body.string();
InputStream is = body.byteStream();
//Reader reader = body.charStream();

//获的图片
final Bitmap bitmap = BitmapFactory.decodeStream(is);

//主线程更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});

//关闭输入流
is.close();

}else {

Log.d(TAG,"响应失败");
}
}
});
}

六. 源码

OkHttpTest

参考文章

界面提交方式-Get和Post

上传和下载视频到本地服务器

文加图, 理解Http请求与响应

OkHttp使用详解

Android 网络(三) HttpURLConnection OkHttp

修改php文件上传的大小限制upload_max_filesize

PHP使用之修改php.ini 配置文件(Mac)