Android使用OKHttp库实现视频文件的上传到服务器功能

1 服务器接口简介

此处我使用的服务器接口是使用Flask编写,具体实现代码:

# -*- coding: utf-8 -*-
from flask import Flask, render_template, jsonify, request
import time
import os
import base64
app = Flask(__name__)
UPLOAD_FOLDER = 'E:\myupload\picture'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
basedir = os.path.abspath(os.path.dirname(__file__))
ALLOWED_EXTENSIONS = set(['txt', 'png', 'jpg', 'xls', 'JPG', 'PNG', 'xlsx', 'gif', 'GIF','mp4'])
# 用于判断文件后缀
def allowed_file(filename):
 return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
# 上传文件
@app.route('/api/upload', methods=['POST'], strict_slashes=False)
def api_upload():
 file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER'])
 if not os.path.exists(file_dir):
  os.makedirs(file_dir)
 f = request.files['myfile'] # 从表单的file字段获取文件,myfile为该表单的name值
 if f and allowed_file(f.filename): # 判断是否是允许上传的文件类型
  fname = f.filename
  print fname
  ext = fname.rsplit('.', 1)[1] # 获取文件后缀
  unix_time = int(time.time())
  new_filename = str(unix_time) + '.' + ext # 修改了上传的文件名
  f.save(os.path.join(file_dir, new_filename)) # 保存文件到upload目录
  print new_filename
  token = base64.b64encode(new_filename)
  print token
  return jsonify({"errno": 0, "errmsg": "上传成功", "token": token})
 else:
  return jsonify({"errno": 1001, "errmsg": "上传失败"})
if __name__ == '__main__':
 app.run(debug=True)

2 Android端代码实现

代码分三部分:

分别是xml布局文件,Activity类,和Okhttp网络通信类。

2.1 xml布局文件

activity_video_upload.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical" >
 <LinearLayout
  android:layout_width="wrap_content"
  android:layout_marginLeft="10dp"
  android:layout_marginRight="10dp"
  android:layout_height="60dp"
  android:layout_marginTop="80dp"
  android:orientation="horizontal">
  <TextView
   android:layout_width="match_parent"
   android:layout_height="50dp"
   android:layout_gravity="center_vertical"
   android:gravity="center"
   android:text="视频名称:"
   android:textColor="@color/black2"
   android:textSize="18dp"/>
  <EditText
   android:id="@+id/upload_video_name"
   android:layout_width="280dp"
   android:layout_height="50dp"
   android:layout_gravity="center_vertical"
   android:hint="请输入上传视频名称"
   android:layout_marginLeft="5dp"
   android:textSize="18dp"
   />
 </LinearLayout>
 <Button
  android:id="@+id/video_select"
  android:layout_width="match_parent"
  android:layout_height="44dp"
  android:layout_marginLeft="100dp"
  android:layout_marginRight="100dp"
  android:layout_marginTop="80dp"
  android:background="@drawable/exit_btn_blue"
  android:text="选择视频"
  android:textStyle="bold"
  android:textColor="@android:color/white"
  android:textSize="20sp"/>
 <Button
  android:id="@+id/video_upload"
  android:layout_width="match_parent"
  android:layout_height="44dp"
  android:layout_marginLeft="100dp"
  android:layout_marginRight="100dp"
  android:layout_marginTop="40dp"
  android:background="@drawable/exit_btn_blue"
  android:text="点击上传"
  android:textStyle="bold"
  android:textColor="@android:color/white"
  android:textSize="20sp"/>
 <TextView
  android:id="@+id/post_text"
  android:layout_marginTop="40dp"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:gravity="center"
  android:text="0" />
 <ProgressBar
  android:id="@+id/post_progress"
  android:layout_marginLeft="20dp"
  android:layout_marginRight="20dp"
  style="?android:attr/progressBarStyleHorizontal"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:max="100" />
</LinearLayout>

2.2 Activity类

VideoUploadActivity类:

package com.liu.dance.video;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.liu.dance.R;
import com.liu.dance.util.HttpUtil;
import com.liu.dance.util.ProgressListener;
import java.io.File;
import java.net.URI;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
public class VideoUploadActivity extends AppCompatActivity {
 public static final String TAG = VideoUploadActivity.class.getName();
 public final static int VEDIO_KU = 101;
 private String path = "";//文件路径
 private ProgressBar post_progress;
 private TextView post_text;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_video_upload);
  getSupportActionBar().setTitle("视频上传");
  getSupportActionBar().setDisplayHomeAsUpEnabled(true);
  final EditText video_name = (EditText)findViewById(R.id.upload_video_name);
  post_progress = (ProgressBar) findViewById(R.id.post_progress);
  post_text = (TextView) findViewById(R.id.post_text);
  findViewById(R.id.video_select).setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
    seleteVedio();
    video_name.setText(path);
   }
  });
  findViewById(R.id.video_upload).setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View view) {
//    Toast.makeText(VideoUploadActivity.this, "路径:"+basePath, Toast.LENGTH_LONG).show();
    if(path.equals(""))
     Toast.makeText(VideoUploadActivity.this, "请选择视频后,再点击上传!", Toast.LENGTH_LONG).show();
    else {
     File file = new File( path);
     String postUrl = "http://120.79.82.151/api/upload";
     HttpUtil.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);
    }
   }
  });
 }
 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  switch (item.getItemId()) {
   case android.R.id.home:
    finish();
    break;
   default:
    break;
  }
  return super.onOptionsItemSelected(item);
 }
 public void seleteVedio() {
  // TODO 启动相册
  Intent intent = new Intent();
  intent.setType("video/*");
  intent.setAction(Intent.ACTION_GET_CONTENT);
  intent.addCategory(Intent.CATEGORY_OPENABLE);
  startActivityForResult(intent,VideoUploadActivity.VEDIO_KU);
 }
 /**
  * 选择回调
  */
 @Override
 public void onActivityResult(int requestCode, int resultCode, Intent data) {
  switch (requestCode) {
   // TODO 视频
   case VideoUploadActivity.VEDIO_KU:
    if (resultCode == Activity.RESULT_OK) {
     try {
      Uri uri = data.getData();
      uri = geturi(this, data);
      File file = null;
      if (uri.toString().indexOf("file") == 0) {
       file = new File(new URI(uri.toString()));
       path = file.getPath();
      } else {
       path = getPath(uri);
       file = new File(path);
      }
      if (!file.exists()) {
       break;
      }
      if (file.length() > 100 * 1024 * 1024) {
//       "文件大于100M";
       break;
      }
      //视频播放
//      mVideoView.setVideoURI(uri);
//      mVideoView.start();
      //开始上传视频,
//      submitVedio();
     } catch (Exception e) {
      String a=e+"";
     } catch (OutOfMemoryError e) {
      String a=e+"";
     }
    }
    break;
  }
 }
 public static Uri geturi(Context context, android.content.Intent intent) {
  Uri uri = intent.getData();
  String type = intent.getType();
  if (uri.getScheme().equals("file") && (type.contains("image/"))) {
   String path = uri.getEncodedPath();
   if (path != null) {
    path = Uri.decode(path);
    ContentResolver cr = context.getContentResolver();
    StringBuffer buff = new StringBuffer();
    buff.append("(").append(MediaStore.Images.ImageColumns.DATA).append("=")
      .append("'" + path + "'").append(")");
    Cursor cur = cr.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
      new String[] { MediaStore.Images.ImageColumns._ID },
      buff.toString(), null, null);
    int index = 0;
    for (cur.moveToFirst(); !cur.isAfterLast(); cur.moveToNext()) {
     index = cur.getColumnIndex(MediaStore.Images.ImageColumns._ID);
     // set _id value
     index = cur.getInt(index);
    }
    if (index == 0) {
     // do nothing
    } else {
     Uri uri_temp = Uri
       .parse("content://media/external/images/media/"
         + index);
     if (uri_temp != null) {
      uri = uri_temp;
      Log.i("urishi", uri.toString());
     }
    }
   }
  }
  return uri;
 }
 private String getPath(Uri uri) {
  String[] projection = {MediaStore.Video.Media.DATA};
  Cursor cursor = managedQuery(uri, projection, null, null, null);
  int column_index = cursor
    .getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
  cursor.moveToFirst();
  return cursor.getString(column_index);
 }
}

2.3 Okhttp网络通信类

HttpUtil类:

package com.liu.dance.util;
import android.util.Log;
import java.io.File;
import java.util.concurrent.TimeUnit;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
/**
 * Created by 舞动的心 on 2018/3/5.
 */
public class HttpUtil {
 private static OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10000, TimeUnit.MILLISECONDS)
   .readTimeout(10000,TimeUnit.MILLISECONDS)
   .writeTimeout(10000, TimeUnit.MILLISECONDS).build();
 public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
 public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");public static void postFile(String url, final ProgressListener listener, okhttp3.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("myfile",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);
 }
}

ProgressListener接口:

package com.liu.dance.util;
/**
 * Created by 舞动的心 on 2018/3/8.
 */
public interface ProgressListener {
 void onProgress(long currentBytes, long contentLength, boolean done);
}

ProgressModel类:

package com.liu.dance.util;
import android.os.Parcel;
import android.os.Parcelable;
/**
 * Created by 舞动的心 on 2018/3/8.
 */
public class ProgressModel implements Parcelable {
 private long currentBytes;
 private long contentLength;
 private boolean done = false;
 public ProgressModel(long currentBytes, long contentLength, boolean done) {
  this.currentBytes = currentBytes;
  this.contentLength = contentLength;
  this.done = done;
 }
 public long getCurrentBytes() {
  return currentBytes;
 }
 public void setCurrentBytes(long currentBytes) {
  this.currentBytes = currentBytes;
 }
 public long getContentLength() {
  return contentLength;
 }
 public void setContentLength(long contentLength) {
  this.contentLength = contentLength;
 }
 public boolean isDone() {
  return done;
 }
 public void setDone(boolean done) {
  this.done = done;
 }
 private static final Creator<ProgressModel> CREATOR = new Creator<ProgressModel>() {
  @Override
  public ProgressModel createFromParcel(Parcel parcel) {
   return new ProgressModel(parcel);
  }
  @Override
  public ProgressModel[] newArray(int i) {
   return new ProgressModel[i];
  }
 };
 @Override
 public int describeContents() {
  return 0;
 }
 @Override
 public void writeToParcel(Parcel parcel, int i) {
  parcel.writeLong(currentBytes);
  parcel.writeLong(contentLength);
  parcel.writeByte((byte) (done==true?1:0));
 }
 protected ProgressModel(Parcel parcel) {
  currentBytes = parcel.readLong();
  contentLength = parcel.readLong();
  done = parcel.readByte()!=0;
 }
}

ProgressRequestBody类:

package com.liu.dance.util;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;
/**
 * Created by 舞动的心 on 2018/3/8.
 */
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);
   }
  };
 }
}

界面效果:

总结

以上所述是小编给大家介绍的Android使用OKHttp库实现视频文件的上传到服务器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android中okhttp3使用详解

    一.引入包 在项目module下的build.gradle添加okhttp3依赖 compile 'com.squareup.okhttp3:okhttp:3.3.1' 二.基本使用 1.okhttp3 Get 方法 1.1 .okhttp3 同步 Get方法 /** * 同步Get方法 */ private void okHttp_synchronousGet() { new Thread(new Runnable() { @Override public void run() { try {

  • android 开发中使用okhttp上传文件到服务器

    开发android手机客户端,常常会需要上传文件到服务器,比如:你手机里的照片. 使用okhttp会是一个很好的选择.它使用很简单,而且运行效率也很高. 首先,在 app/build.gradle 的 dependencies 增加 implementation 'com.squareup.okhttp3:okhttp:3.8.1' 可以参照如下代码 apply plugin: 'com.android.application' apply plugin: 'kotlin-android' ap

  • Android OkHttp Post上传文件并且携带参数实例详解

    Android OkHttp Post上传文件并且携带参数 这里整理一下 OkHttp 的 post 在上传文件的同时,也要携带请求参数的方法. 使用 OkHttp 版本如下: compile 'com.squareup.okhttp3:okhttp:3.4.1' 代码如下: protected void post_file(final String url, final Map<String, Object> map, File file) { OkHttpClient client = n

  • android Retrofit2+okHttp3使用总结

    使用前准备 Build.gradle文件配置 dependencies配置 compile 'com.squareup.retrofit2:retrofit:2.0.0' compile 'com.squareup.retrofit2:converter-gson:2.0.0' compile 'com.squareup.okhttp3:logging-interceptor:3.2.0' 网络框架搭建 服务创建类封装(HTTP): public class ServiceGenerator {

  • Android OkHttp 结合php 多图片上传实例

    今天写项目的时候需要多图片上传,就用okhttp简单写一个例子. public class MainActivity extends AppCompatActivity { private OkHttpClient client; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ma

  • Android OKHTTP的单例和再封装的实例

    Android OKHTTP的单例和再封装的实例 /** * Created by zm on 16-2-1 * okhttp的再封装,对于2.x版本,3.x版本将原有对okhttpclient配置 * 改成了builder模式配 * 置,对于超时.代理.dns,okhttp已经做好了配置, * 若不需要特殊配置,可以跳过 */ public class OkHttpUtil { private static OkHttpClient singleton; //非常有必要,要不此类还是可以被ne

  • android通过okhttpClient下载网页内容的实例代码

    有时候我们需要通过自己的缓存机制来缓存网页内容,当没有网的时候显示本地的缓存,当有网的时候取最新的继续缓存到本地. 主要机制: 通过AsyncTask异步AsyncTask请求,将得到的response.body()缓存起来. 主要代码如下: //通过OkHttpClient加载html的方式先判断网页是否能走通 class WebViewStatusRequester extends AsyncTask<String, String, Integer> { String url; @Over

  • Android Okhttp请求查询购物车的实例代码

    查询购物车的model层 public class SelectCarModel { private String url="http://120.27.23.105/product/getCarts"; private HashMap<String, String> map = new HashMap<>(); public void verifySelectCarInfo(int uid, final ISelectCarPresenter iSelectC

  • Android使用OkHttp上传图片的实例代码

    简介 上传图片是一个APP的常见功能,可以是通过OOS上传到阿里云,也可以直接上传到Server后台,OOS有提供相应的SDK,此处忽略.下面通过OkHttp来实现图片的上传 代码 直接上代码UploadFileHelper.kt object UploadFileHelper { //--------ContentType private val MEDIA_OBJECT_STREAM = MediaType.parse("multipart/form-data") //------

  • Android中实现OkHttp上传文件到服务器并带进度

    在上一讲中 OkHttp下载文件并带进度条 中,我们知道怎样去下载文件了.那上传文件呢 一.编写服务器端 在上一讲服务器下新建UploadFileServlet,代码如下:然后重启服务器! @WebServlet("/UploadFileServlet") @MultipartConfig public class UploadFileServlet extends HttpServlet { private static final long serialVersionUID = 1

  • 详解Android中OkHttp3的例子和在子线程更新UI线程的方法

    okHttp用于android的http请求.据说很厉害,我们来一起尝尝鲜.但是使用okHttp也会有一些小坑,后面会讲到如何掉进坑里并爬出来. 首先需要了解一点,这里说的UI线程和主线程是一回事儿.就是唯一可以更新UI的线程.这个只是点会在给okHttp填坑的时候用到.而且,这个内容本身在日常的开发中也经常用到,值得好好学一学. okHttp发起同步请求 第一个列子是一个同步请求的例子. private void performSyncHttpRequest() { OkHttpClient

  • Android 封装Okhttp+Retrofit+RxJava,外加拦截器实例

    1.创建一个接口,用来定义接口使用的 public interface Api { @POST("product/getProductDetail") Observable<Goods_Bean> getGoods(@QueryMap Map<String,String> map); @POST("product/addCart") Observable<Add_Bean> getAdd(@QueryMap Map<Stri

  • Android okhttp3.0忽略https证书的方法

    最近公司项目需要,网络协议支持https,之前接触不多,所以这次想总结一下https在android开发中的相关内容 一.https证书 对于https和证书的概念,大家可以自行搜索百度. 证书分两种: 1.花钱向认证机构购买的证书,(我们公司买的证书一个就需要4000元,TMD,还不如多租一台服务器).服务器如果使用了此类证书的话,那对于移动端来说,直接可以忽略此证书,直接用https访问.与之不同的是ios内置了很多信任的证书,所以他们不需要做任何操作 2.另一种是自己制作的证书,使用此类证

  • Android使用OKHTTP解析JSON数据的实例代码

    为了代码重用,我们首先封装一个类.这个类是HttpUtil HttpUtil.java package com.example.asus.networktest; import okhttp3.OkHttpClient; import okhttp3.Request; public class HttpUtil { public static void sendOkHttpRequest(final String address, final okhttp3.Callback callback)

  • Android使用OkHttp请求自签名的https网站的示例

    前言 很多公司考虑到安全问题,项目中都采用https加密协议进行数据传输.但是一些公司又不想花一笔钱去CA申请证书,所以就采用自签名的证书. OkHttp默认是可以访问通过CA认证的HTTPS链接,例如百度首页也是https链接(https://www.baidu.com/).但是如果是你们公司自签名(即自己用keytool生成的证书,而不是采用通过CA认证的证书)的服务器,OkHttp是无法访问的,例如访问12306网站(https://kyfw.12306.cn/otn/),会报如下错误:

  • android中实现OkHttp下载文件并带进度条

    OkHttp是比较火的网络框架,它支持同步与异步请求,支持缓存,可以拦截,更方便下载大文件与上传文件的操作.下面我们用OkHttp来下载文件并带进度条! 相关资料: 官网地址:http://square.github.io/okhttp/ github源码地址:https://github.com/square/okhttp 一.服务器端简单搭建 可以参考搭建本地Tomcat服务器及相关配置这篇文章. 新建项目OkHttpServer,在WebContent目录下新建downloadfile目录

  • Android开发之OkHttpUtils的具体使用方法

    一.概述 之前写了篇Android OkHttp完全解析 是时候来了解OkHttp了,其实主要是作为okhttp的普及文章,当然里面也简单封装了工具类,没想到关注和使用的人还挺多的,由于这股热情,该工具类中的方法也是剧增,各种重载方法,以致于使用起来极不方便,实在惭愧. 于是,在这个周末,抽点时间对该工具类,进行了重新的拆解与编写,顺便完善下功能,尽可能的提升其使用起来的方便性和易扩展性. ok,那么目前,该封装库志支持: 一般的get请求 一般的post请求 基于Http的文件上传 文件下载

  • Android OkHttp基本使用详解

    Android系统提供了两种HTTP通信类,HttpURLConnection和HttpClient. 尽管Google在大部分安卓版本中推荐使用HttpURLConnection,但是这个类相比HttpClient实在是太难用,太弱爆了. OkHttp是一个相对成熟的解决方案,据说Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了.所以我们更有理由相信OkHttp的强大. 使用范围 OkHttp支持Android 2.3及其以上版本. 对于Jav

随机推荐