Android中实现OkHttp上传文件到服务器并带进度
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android中实现OkHttp上传文件到服务器并带进度相关的知识,希望对你有一定的参考价值。
在上一讲中 OkHttp下载文件并带进度条 中,我们知道怎样去下载文件了。那上传文件呢
一、编写服务器端
在上一讲服务器下新建UploadFileServlet,代码如下:然后重启服务器!
- @WebServlet("/UploadFileServlet")
- @MultipartConfig
- public class UploadFileServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- public UploadFileServlet() {
- super();
- // TODO Auto-generated constructor stub
- }
- /**
- * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
- * response)
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- this.doPost(request, response);
- }
- /**
- * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
- * response)
- */
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- System.out.println("doPost==");
- request.setCharacterEncoding("utf-8");
- //获取file命名的part,注意要与android端一样
- Part part = request.getPart("file");
- // 获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
- String header = part.getHeader("content-disposition");
- System.out.println(header);
- String fileName = getFileName(header);
- // 存储路径
- String savePath = "D:/huang/upload";
- // 把文件写到指定路径
- part.write(savePath + File.separator + fileName);
- response.setCharacterEncoding("UTF-8");
- PrintWriter writer = response.getWriter();
- writer.print("上传成功");
- }
- public String getFileName(String header) {
- /**
- * header 为 form-data; name="file"; filename="dial.png"
- * String[] tempArr1 =
- * header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别
- * 火狐或者google浏览器下:tempArr1={form-data,name="file",filename=
- * "snmp4j--api.zip"}
- * IE浏览器下:tempArr1={form-data,name="file",filename="E:\\snmp4j--api.zip"}
- */
- String[] tempArr1 = header.split(";");
- /**
- * 火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}
- * IE浏览器下:tempArr2={filename,"E:\\snmp4j--api.zip"}
- */
- String[] tempArr2 = tempArr1[2].split("=");
- // 获取文件名,兼容各种浏览器的写法
- String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\\\") + 1).replaceAll("\\"", "");
- return fileName;
- }
- }
二、Android端
1.布局,上一讲activity_main代码中添加 :
- <Button
- android:id="@+id/ok_post_file"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="上传文件" />
- <TextView
- android:id="@+id/post_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:text="0" />
- <ProgressBar
- android:id="@+id/post_progress"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:max="100" />
2.OkHttpUtil新增上传文件方法:
- public static void postFile(String url, final ProgressListener listener, Callback callback, File...files){
- MultipartBody.Builder builder = new MultipartBody.Builder();
- builder.setType(MultipartBody.FORM);
- Log.i("huang","files[0].getName()=="+files[0].getName());
- //第一个参数要与Servlet中的一致
- builder.addFormDataPart("file",files[0].getName(), RequestBody.create(MediaType.parse("application/octet-stream"),files[0]));
- MultipartBody multipartBody = builder.build();
- Request request = new Request.Builder().url(url).post(new ProgressRequestBody(multipartBody,listener)).build();
- okHttpClient.newCall(request).enqueue(callback);
- }
3.ProgressRequestBody是自定义RequestBody类,用来监听进度:
- public class ProgressRequestBody extends RequestBody {
- public static final int UPDATE = 0x01;
- private RequestBody requestBody;
- private ProgressListener mListener;
- private BufferedSink bufferedSink;
- private MyHandler myHandler;
- public ProgressRequestBody(RequestBody body, ProgressListener listener) {
- requestBody = body;
- mListener = listener;
- if (myHandler==null){
- myHandler = new MyHandler();
- }
- }
- class MyHandler extends Handler {
- //放在主线程中显示
- public MyHandler() {
- super(Looper.getMainLooper());
- }
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what){
- case UPDATE:
- ProgressModel progressModel = (ProgressModel) msg.obj;
- if (mListener!=null)mListener.onProgress(progressModel.getCurrentBytes(),progressModel.getContentLength(),progressModel.isDone());
- break;
- }
- }
- }
- @Override
- public MediaType contentType() {
- return requestBody.contentType();
- }
- @Override
- public long contentLength() throws IOException {
- return requestBody.contentLength();
- }
- @Override
- public void writeTo(BufferedSink sink) throws IOException {
- if (bufferedSink==null){
- bufferedSink = Okio.buffer(sink(sink));
- }
- //写入
- requestBody.writeTo(bufferedSink);
- //刷新
- bufferedSink.flush();
- }
- private Sink sink(BufferedSink sink) {
- return new ForwardingSink(sink) {
- long bytesWritten = 0L;
- long contentLength = 0L;
- @Override
- public void write(Buffer source, long byteCount) throws IOException {
- super.write(source, byteCount);
- if (contentLength==0){
- contentLength = contentLength();
- }
- bytesWritten += byteCount;
- //回调
- Message msg = Message.obtain();
- msg.what = UPDATE;
- msg.obj = new ProgressModel(bytesWritten,contentLength,bytesWritten==contentLength);
- myHandler.sendMessage(msg);
- }
- };
- }
- }
4.在MainActivity添加上传按钮点击事件,代码如下:
- File file = new File(basePath + "/1.mp4");
- String postUrl = "http://192.168.0.104:8080/OkHttpServer/UploadFileServlet";
- OkHttpUtil.postFile(postUrl, new ProgressListener() {
- @Override
- public void onProgress(long currentBytes, long contentLength, boolean done) {
- Log.i(TAG, "currentBytes==" + currentBytes + "==contentLength==" + contentLength + "==done==" + done);
- int progress = (int) (currentBytes * 100 / contentLength);
- post_progress.setProgress(progress);
- post_text.setText(progress + "%");
- }
- }, new Callback() {
- @Override
- public void onFailure(Call call, IOException e) {
- }
- @Override
- public void onResponse(Call call, Response response) throws IOException {
- if (response != null) {
- String result = response.body().string();
- Log.i(TAG, "result===" + result);
- }
- }
- }, file);
相关效果图:
上传完成后,在电脑D:\\huang\\upload下可以看到: