OKHttp3学习笔记-文件上传

来源:互联网 发布:淘宝店铺过期不存在 编辑:程序博客网 时间:2024/05/08 23:22

用TP5框架写了个上传多个文件的表单
HTML代码:

<!DOCTYPE html><html><head>    <title></title></head><body><form action="{:url('uploads')}"enctype="multipart/form-data" method="post">    <input type="file" name="image[]" /> <br>    <input type="file" name="image[]" /> <br>    <input type="file" name="image[]" /> <br>    <input type="submit" value="上传" /></form></body></html>

PHP代码:

public function uploads(){    $files = request()->file('image');    foreach($files as $file){        $info = $file->move(ROOT_PATH . 'public' . DS . 'uploads');        if($info){            // 成功上传后 获取上传信息            // 输出 jpg            echo $info->getExtension();            // 输出 20160820/42a79759f284b767dfcb2a0197904287.jpg            echo $info->getSaveName();            // 输出 42a79759f284b767dfcb2a0197904287.jpg            echo $info->getFilename();        }else{            // 上传失败获取错误信息            echo $file->getError();        }    }}

上传三个很简单的文本文件,通过Fiddler截取Http请求如下

POST http://localhost/index/index/uploads.html HTTP/1.1Host: localhostConnection: keep-aliveContent-Length: 515Cache-Control: max-age=0Origin: http://localhostUpgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36Content-Type: multipart/form-data; boundary=----WebKitFormBoundarymCVtBW9oc2PEnvDjAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8Referer: http://localhost/index/index/indexAccept-Encoding: gzip, deflate, brAccept-Language: zh-CN,zh;q=0.8Cookie: pgv_pvi=6689128448; Phpstorm-ba9458cf=5f1ce810-71dc-4a40-821d-4699b7059873; PHPSESSID=1aq8lag529a7ff75l096928g90------WebKitFormBoundarymCVtBW9oc2PEnvDjContent-Disposition: form-data; name="image[]"; filename="TestFile1.txt"Content-Type: text/plaintest file 1------WebKitFormBoundarymCVtBW9oc2PEnvDjContent-Disposition: form-data; name="image[]"; filename="TestFile2.txt"Content-Type: text/plaintest file 2------WebKitFormBoundarymCVtBW9oc2PEnvDjContent-Disposition: form-data; name="image[]"; filename="TestFile3.txt"Content-Type: text/plaintest file 3------WebKitFormBoundarymCVtBW9oc2PEnvDj--

和不上传文件的Http请求对比,能看到几个显著地不同:

//说明我的请求是提交一个表单,boundary用来区分同时上传的几个文件的标识Content-Type: multipart/form-data; boundary=----WebKitFormBoundarymCVtBW9oc2PEnvDj

除Http的Header以外在Http请求的Body中有对上传的三个文本文件的描述。
这些文件描述的整体格式是“–文件描述–”
对于每个文件描述来说都要用boundary定义的字符串来包裹住
每个文件描述包含的内容是:
Content-Disposition:对上传内容的描述
Content-Type:上传文件的类型
之后就是文件的数据,因为这个例子里上传的是文本类型的,所以在Fiddler中可以正确显示出来,如果是其他类型的文件比如图片或音视频,则显示在Fiddler中的是一大堆的乱码。
但是通过上面的展示我们就已经了解了使用网页上传文件时http的细节。
那么用OKHttp3上传文件是什么样的呢?

val url = "http://192.168.9.80/index/index/uploads"/* 第一个要上传的file */val file1 = File(getExternalStorageDirectory().getAbsolutePath() + "/TestFile1.txt")val fileBody1 = RequestBody.create(MediaType.parse("text/plain"), file1)val file1Name = "testFile1.txt"/* 第二个要上传的文件*/val file2 = File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/TestFile2.txt")val fileBody2 = RequestBody.create(MediaType.parse("text/plain"), file2)val file2Name = "testFile2.txt"/* 第三个要上传的文件*/val file3 = File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/TestFile3.txt")val fileBody3 = RequestBody.create(MediaType.parse("text/plain"), file3)val file3Name = "testFile3.txt"/* form的分割线,自己定义 */val boundary = "----yang--------------------------------------------------------------yang"val mBody = MultipartBody.Builder(boundary).setType(MultipartBody.FORM)    /* 上传了三个文件 */    .addFormDataPart("image[]", file1Name, fileBody1)    .addFormDataPart("image[]", file2Name, fileBody2)    .addFormDataPart("image[]", file3Name, fileBody3)    .build()val okHttpClient = OkHttpClient()val request = Request.Builder()    .url(url)    .post(mBody)    .build()val call = okHttpClient.newCall(request)call.enqueue(object: Callback{    override fun onFailure(p0: Call?, p1: IOException?) {    }    override fun onResponse(p0: Call?, p1: Response?) {    }})

对应的Http请求如下

POST http://192.168.9.80/index/index/uploads HTTP/1.1Content-Type: multipart/form-data; boundary=----yang--------------------------------------------------------------yangContent-Length: 719Host: 192.168.9.80Connection: Keep-AliveAccept-Encoding: gzipCookie: PHPSESSID=3ignhso5d41h591f0nn4cduhf4User-Agent: okhttp/3.8.1------yang--------------------------------------------------------------yangContent-Disposition: form-data; name="image[]"; filename="testFile1.txt"Content-Type: text/plainContent-Length: 11test file 1------yang--------------------------------------------------------------yangContent-Disposition: form-data; name="image[]"; filename="testFile2.txt"Content-Type: text/plainContent-Length: 11test file 2------yang--------------------------------------------------------------yangContent-Disposition: form-data; name="image[]"; filename="testFile3.txt"Content-Type: text/plainContent-Length: 11test file 3------yang--------------------------------------------------------------yang--

通过这样的对比分析,我们就能够知道在我们使用OKHttp3进行文件上传的时候,到底都是在做什么了,说白了,实际上就是去模仿浏览器中的操作,把那些原本由浏览器帮我们做好的事情,自己去框架的接口去实现而已。