金鞍玉勒寻芳客,未信我庐别有春。这篇文章主要讲述Android使用OKHttp库实现视频文件的上传到服务器相关的知识,希望能为你提供帮助。
目录
1 服务器接口简介
2 Android端代码实现
2.1 xml布局文件
2.2 Activity类
2.3 Okhttp网络通信类
1 服务器接口简介此处我使用的服务器接口是使用Flask编写,具体实现代码:
# -*- coding: utf-8 -*- from flask import Flask, render_template, jsonify, request import time import os import base64app = 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 tokenreturn jsonify({"errno": 0, "errmsg": "上传成功", "token": token}) else: return jsonify({"errno": 1001, "errmsg": "上传失败"})if __name__ == \'__main__\': app.run(debug=True)
参考文章:https://www.cnblogs.com/mosson/p/6163233.html
附加使用PostMan测试上传文件的操作方法:http://blog.csdn.net/u013420865/article/details/69665180
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(); publicfinal 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) { Stringa=e+""; } catch (OutOfMemoryError e) { Stringa=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); } }; }}
界面效果:
文章图片
参考文章:http://blog.csdn.net/gary__123456/article/details/74157403
【Android使用OKHttp库实现视频文件的上传到服务器】
推荐阅读
- 仅仅通过Application监听用户行为及App的在线状态和在线时长
- 安卓实现下拉刷新效果
- ApplicationContext获取
- Android性能优化--OOM
- 移动通信中使用的术语
- 临时排序路由算法(TORA)
- 移动通信的路由
- 移动通信中的一些开放性研究主题
- Win8系统Smartscreen筛选器界面变灰无法设置怎样办