这几天做实习项目遇到的安卓端(客户端)选择本地文件(演示对象为视频)上传到web端(即:SpringMVC服务端)的一个需求。首先是android调用系统的选择本地文件界面,然后在重写的函数onActivityResult()中去获取到文件的Uri地址,在利用这个Uri地址进行文件的上传操作。服务端是实习的带队老师帮忙搭建的一个SpringMVC的web端吧,利用controller实现把上传的文件获取并保存到web端的指定目录下。感觉可以记录一下。 p.s> 本来项目内用websocket连接上了服务端的,准备用websocket直接上传文件的,但是由于之前没用过这个websocket技术(博主是个小菜瓜大佬轻喷),出现了一个好像是缓存buffer不足或者未开启异步发送byte[]文件的报错,试了一下没做出来wesocket的文件上传,所以转而转向SpringMVC的上传,如果有用websocket实现过android上传文件到服务端的大佬可以指教或者交流一下~
服务端 具体的服务端配置是我从实习的指导老师那直接拿过来用的,在此基础上添加的代码内容,所以怎么创建一个SpringMVC的服务端就不详细说了,这里就只说一下涉及的controler和实体类,以及实际遇到的返回结果无法转化为json的问题。这里放一下服务端demo参考的 springmvc服务端+android客户端的文件上传 博客
(后面我又自己趁着假期把服务端自己搭建了一遍:主要是自己搭建一个SpringMVC项目出来并且给搭建上hibernate就行用eclipse搭建自己的SpringMVC+hibernate小demo ,ps这个链接的项目有一点不一样:我自己搭建的是用的MySQL而不是postgresql,其次自己搭建的项目是基于Maven的,所以导包操作可以在pom.xml中完成)
服务端配置 这里放一下jar包的下载地址 吧
红色框内是本次的相关项
详细的SpringMVC项目的创建我就不再赘述了,百度应该有一大把的博客有的。
所需上传的jar包 这里我用的jackson的相关jar是2.9.8版本————
jackson-annotations-2.9.8.jar
jackson-core-2.9.8.jar
jackson-databind-2.9.8.jar
上传文件的jar包————
commons-fileupload-1.2.2.jar
commons-io-2.6.jar
文件下载下来后直接Ctrl C+V到WebContent/WEB-INF/lib里就行了
(之前并没有开发过SpringMVC项目,而且这次拿到的项目,老师也没有用maven以及porm.xml,所以拿到项目后我是直接导入的,如果我说的有不对的地方还请指正)
springmvc.xml配置 springmvc.xml 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 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:mvc ="http://www.springframework.org/schema/mvc" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd" > <mvc:annotation-driven /> <context:component-scan base-package ="com.spring.handlers.controller" > </context:component-scan > <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name = "prefix" value ="/WEB-INF/views/" > </property > <property name = "suffix" value = ".jsp" > </property > </bean > <bean id ="multipartResolver" class ="org.springframework.web.multipart.commons.CommonsMultipartResolver" > <property name ="defaultEncoding" value ="utf-8" > </property > <property name ="maxUploadSize" value ="10485760000" > </property > <property name ="maxInMemorySize" value ="40960" > </property > </bean > </beans >
实体类 用一个result的实体类来返回post的响应结果
result实体类代码 result.java 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 import org.springframework.stereotype.Component;@Component public class Result { private String path; private int code; private String message; public String getPath () { return path; } public void setPath (String path) { this .path = path; } public int getCode () { return code; } public void setCode (int code) { this .code = code; } public void setMessage (String message) { this .message = message; } public String getMessage () { return message; } }
Controller 添加一个UploadController来实现对android端post请求的接受
UploadController.java 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 package com.spring.handlers.controller;import java.io.File;import java.io.IOException;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.multipart.MultipartFile;@Controller public class UploadController { @Resource private Result result; @RequestMapping (value ="/mobile/uploadfile" , produces = "application/json;charset=utf-8" ) @ResponseBody public Result uploadPhone (@RequestParam(value="file" ,required=false ) MultipartFile file,HttpServletRequest request) throws IllegalStateException, IOException { System.out.println("进入uploadPhone方法" ); String path=uploadFile(file, request); result.setCode(200 ); result.setPath(path); System.out.println(path); result.setMessage("上传成功" ); System.out.println(result.getMessage()); return result; } private String uploadFile (MultipartFile file,HttpServletRequest request) throws IOException { System.out.println("进入uploadFile方法" ); String path=request.getSession().getServletContext().getRealPath("upload" ); String fileName=file.getOriginalFilename(); File targetFile=new File(path,fileName); if (!targetFile.exists()){ targetFile.mkdirs(); } file.transferTo(targetFile); return targetFile.getAbsolutePath(); } }
android端 添加权限 添加网络访问权限 在AndroidManifest.xml中,manifest标签中添加权限:
1 <uses-permission android:name="android.permission.INTERNET" />
添加文件存储访问权限 在AndroidManifest.xml中,manifest标签中添加权限:
1 2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
AndroidManifest.xml文件 AndroidManifest.xml 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 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android ="http://schemas.android.com/apk/res/android" package ="com.example.uploadtest" > <uses-permission android:name ="android.permission.INTERNET" /> <uses-permission android:name ="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name ="android.permission.READ_EXTERNAL_STORAGE" /> <application android:allowBackup ="true" android:icon ="@mipmap/ic_launcher" android:label ="@string/app_name" android:roundIcon ="@mipmap/ic_launcher_round" android:supportsRtl ="true" android:theme ="@style/AppTheme" > <activity android:name =".MainActivity" > <intent-filter > <action android:name ="android.intent.action.MAIN" /> <category android:name ="android.intent.category.LAUNCHER" /> </intent-filter > </activity > </application > </manifest >
android选择本地文件 这里主要用到的就是隐式Intent,实现android调用系统文件选择器,并在重写的函数onActivityResult()里去获取文件的Uri值,例如: content://com.android.providers.media.documents/document/video%3A184539
选择文件的前端代码 activity_main.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android ="http://schemas.android.com/apk/res/android" xmlns:app ="http://schemas.android.com/apk/res-auto" xmlns:tools ="http://schemas.android.com/tools" android:layout_width ="match_parent" android:layout_height ="match_parent" android:gravity ="center" android:orientation ="vertical" tools:context =".MainActivity" > <TextView android:id ="@+id/show_info" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="上传文件测试" /> <Button android:layout_width ="match_parent" android:layout_height ="wrap_content" android:onClick ="ChooseVideo" android:text ="选择视频文件" /> </LinearLayout >
android选择本地文件的Activity代码 MainActivity.java 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 package com.example.uploadtest;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.util.Log;import android.view.View;import android.widget.TextView;import com.example.uploadtest.myUtils.AndroidUploadFile;import com.example.uploadtest.myUtils.FileTool;import org.apache.http.client.ClientProtocolException;import java.io.File;import java.io.IOException;public class MainActivity extends AppCompatActivity { private final int CHOOSE_VIDEO=0x0b ; private Uri fileUri; private TextView tv; private String Host = "192.168.x.xxx" ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.show_info); } public void ChooseVideo (View v) { Intent chooseVideo = new Intent(Intent.ACTION_OPEN_DOCUMENT); chooseVideo.setDataAndType(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/*" ); chooseVideo.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true ); startActivityForResult(chooseVideo, CHOOSE_VIDEO); } @SuppressLint ("MissingSuperCall" ) @Override protected void onActivityResult (int requestCode, int resultCode, Intent intent) { switch (requestCode){ case CHOOSE_VIDEO: if (resultCode==RESULT_OK){ if (null != intent.getData()){ try { fileUri = intent.getData(); Log.i("URI" ,fileUri.toString()); tv.setText(fileUri.toString()); }catch (Exception e){e.printStackTrace();} }else { Log.e("onActivityResult" ,"intent.getData()回调数据为空!!!!!!" ); } } break ; } } }
文件处理类 之前我们实现的是调用android系统的视频文件选择器,选择并返回了文件的Uri地址,但是返回的仅仅是Uri地址,并非真实地址,这里我放一个文件Uri地址转真实地址的文件处理类FileTool类,用来把得到的Uri转化为对应文件的真实地址, 例如: 之前的Uri地址:content://com.android.providers.media.documents/document/video%3A184539, 利用这个类转化的真实路径为:/storage/emulated/0/Pictures/Screenshots/SVID_20190726_092605_1.mp4。
FileTool.java 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 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 package com.example.uploadtest.myUtils;import android.content.ContentResolver;import android.content.ContentUris;import android.content.Context;import android.database.Cursor;import android.net.Uri;import android.os.Build;import android.os.Environment;import android.provider.DocumentsContract;import android.provider.MediaStore;import android.text.TextUtils;import android.util.Log;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;public class FileTool { public static File getFileFromUri (Uri uri, Context context) { if (uri == null ) { return null ; } switch (uri.getScheme()) { case "content" : return getFileFromContentUri(uri, context); case "file" : return new File(uri.getPath()); default : return null ; } } private static File getFileFromContentUri (Uri contentUri, Context context) { if (contentUri == null ) { return null ; } File file = null ; String filePath = new String(); String fileName; String[] filePathColumn = {MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME}; ContentResolver contentResolver = context.getContentResolver(); Cursor cursor = contentResolver.query(contentUri, filePathColumn, null , null , null ); if (cursor != null ) { cursor.moveToFirst(); try { filePath = getFilePathByUri(context,contentUri); }catch (Exception e){ } fileName = cursor.getString(cursor.getColumnIndex(filePathColumn[1 ])); cursor.close(); Log.e("filePath" ,filePath); Log.e("fileName" ,"\nfilePathColumn[1]:" +filePathColumn[1 ]); if (!TextUtils.isEmpty(filePath)) { file = new File(filePath); } if (!file.exists() || file.length() <= 0 || TextUtils.isEmpty(filePath)) { Log.e("测试" ,"记删" ); filePath = getPathFromInputStreamUri(context, contentUri, fileName); } if (!TextUtils.isEmpty(filePath)) { file = new File(filePath); } } return file; } public static String getPathFromInputStreamUri (Context context, Uri uri, String fileName) { InputStream inputStream = null ; String filePath = null ; if (uri.getAuthority() != null ) { try { inputStream = context.getContentResolver().openInputStream(uri); File file = createTemporalFileFrom(context, inputStream, fileName); filePath = file.getPath(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null ) { inputStream.close(); } } catch (Exception e) { e.printStackTrace(); Log.e("FileTool" ,e.toString()); } } } return filePath; } private static File createTemporalFileFrom (Context context, InputStream inputStream, String fileName) throws IOException { File targetFile = null ; if (inputStream != null ) { int read; byte [] buffer = new byte [32 * 1024 ]; targetFile = new File(fileName); if (targetFile.exists()) { targetFile.delete(); } OutputStream outputStream = new FileOutputStream(targetFile); while ((read = inputStream.read(buffer)) != -1 ) { outputStream.write(buffer, 0 , read); } outputStream.flush(); try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return targetFile; } public static byte [] uriTobytes(final Uri uri,Context context) { Log.e("uriTobytes" ,"进入uriTobytes方法" ); byte [] data = null ; try { FileInputStream fileInputStream = new FileInputStream(getFileFromContentUri(uri,context)); int length = fileInputStream.available(); data = new byte [length]; fileInputStream.read(data); fileInputStream.close(); }catch (Exception e){ e.printStackTrace(); Log.e("uriTobytes" ,e.toString()); } return data; } public static String getFilePathByUri (Context context, Uri uri) { String path = null ; if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { path = uri.getPath(); return path; } if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null , null , null ); if (cursor != null ) { if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); if (columnIndex > -1 ) { path = cursor.getString(columnIndex); } } cursor.close(); } return path; } if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (DocumentsContract.isDocumentUri(context, uri)) { if (isExternalStorageDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":" ); final String type = split[0 ]; if ("primary" .equalsIgnoreCase(type)) { path = Environment.getExternalStorageDirectory() + "/" + split[1 ]; return path; } } else if (isDownloadsDocument(uri)) { final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads" ), Long.valueOf(id)); path = getDataColumn(context, contentUri, null , null ); return path; } else if (isMediaDocument(uri)) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":" ); final String type = split[0 ]; Uri contentUri = null ; if ("image" .equals(type)) { contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } else if ("video" .equals(type)) { contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; } else if ("audio" .equals(type)) { contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; } final String selection = "_id=?" ; final String[] selectionArgs = new String[]{split[1 ]}; path = getDataColumn(context, contentUri, selection, selectionArgs); return path; } } } return null ; } private static String getDataColumn (Context context, Uri uri, String selection, String[] selectionArgs) { Cursor cursor = null ; final String column = "_data" ; final String[] projection = {column}; try { cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null ); if (cursor != null && cursor.moveToFirst()) { final int column_index = cursor.getColumnIndexOrThrow(column); return cursor.getString(column_index); } } finally { if (cursor != null ) cursor.close(); } return null ; } private static boolean isExternalStorageDocument (Uri uri) { return "com.android.externalstorage.documents" .equals(uri.getAuthority()); } private static boolean isDownloadsDocument (Uri uri) { return "com.android.providers.downloads.documents" .equals(uri.getAuthority()); } private static boolean isMediaDocument (Uri uri) { return "com.android.providers.media.documents" .equals(uri.getAuthority()); } }
然后就可以在MainActivity.java内注释的地方加入代码调用FileTool类处理Uri地址了:
1 2 String path= FileTool.getFilePathByUri(this ,fileUri); Log.e("打印path" ,path);
文件上传类 之后需要一个AndroidUploadFile类,利用http的post请求把文件推到服务端去,并且利用返回消息在android端判断是否有上传成功。
在app中添加依赖 因为上传文件时需要用到http请求,所以在app的gradle导入一下apache的http依赖项:
1 implementation 'org.apache.httpcomponents:httpmime:4.5.10'
放一下build.gradle(app)的代码:
build.gradle(app) 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 apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "29.0.2" defaultConfig { applicationId "com.example.uploadtest" minSdkVersion 19 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt' ), 'proguard-rules.pro' } } packagingOptions { exclude 'META-INF/DEPENDENCIES' } } dependencies { implementation fileTree (dir: 'libs' , include : ['*.jar' ]) implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'org.apache.httpcomponents:httpmime:4.5.10' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' }
AndroidUploadFile类 AndroidUploadFile.java 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 package com.example.uploadtest.myUtils;import android.util.Log;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.HttpStatus;import org.apache.http.HttpVersion;import org.apache.http.StatusLine;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.mime.MultipartEntity;import org.apache.http.entity.mime.content.ContentBody;import org.apache.http.entity.mime.content.FileBody;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.CoreProtocolPNames;import org.apache.http.util.EntityUtils;import java.io.File;import java.io.IOException;public class AndroidUploadFile { public static String uploadFile (String filePath,String urlServer) throws ClientProtocolException, IOException, IOException { HttpClient httpClient=new DefaultHttpClient(); httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); HttpPost httpPost=new HttpPost(urlServer); MultipartEntity multipartEntity=new MultipartEntity(); File file=new File(filePath); ContentBody contentBody=new FileBody(file); multipartEntity.addPart("file" ,contentBody); httpPost.setEntity(multipartEntity); HttpResponse response=httpClient.execute(httpPost); Log.e("我再打印一下" ,response.toString()); StatusLine statusLine= response.getStatusLine(); if (statusLine.getStatusCode() == HttpStatus.SC_OK){ HttpEntity entity=response.getEntity(); String result= EntityUtils.toString(entity); Log.i("TAG" ,"*******" +result); }else { HttpEntity entity=response.getEntity(); String result= EntityUtils.toString(entity); Log.i("TAG" ,"*******" +result); Log.e("StatusCode" ,"\n statusLine.getStatusCode():" + statusLine.getStatusCode()); Log.i("TAG" ,"请求出了问题" ); } return null ; } }
并在MainActivity中调用
1 AndroidUploadFile.uploadFile(file.getAbsolutePath(), "http://" +Host+":8080/PortalSystemAdmin/mobile/uploadfile" );
贴一下完整的MainActivity.class代码 MainActivity.class 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 80 81 82 package com.example.uploadtest;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.util.Log;import android.view.View;import android.widget.TextView;import com.example.uploadtest.myUtils.AndroidUploadFile;import com.example.uploadtest.myUtils.FileTool;import org.apache.http.client.ClientProtocolException;import java.io.File;import java.io.IOException;public class MainActivity extends AppCompatActivity { private final int CHOOSE_VIDEO=0x0b ; private Uri fileUri; private TextView tv; private String Host = "192.168.x.xxx" ; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView)findViewById(R.id.show_info); } public void ChooseVideo (View v) { Intent chooseVideo = new Intent(Intent.ACTION_OPEN_DOCUMENT); chooseVideo.setDataAndType(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/*" ); chooseVideo.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true ); startActivityForResult(chooseVideo, CHOOSE_VIDEO); } @SuppressLint ("MissingSuperCall" ) @Override protected void onActivityResult (int requestCode, int resultCode, Intent intent) { switch (requestCode){ case CHOOSE_VIDEO: if (resultCode==RESULT_OK){ if (null != intent.getData()){ try { fileUri = intent.getData(); Log.i("URI" ,fileUri.toString()); tv.setText(fileUri.toString()); String path= FileTool.getFilePathByUri(this ,fileUri); Log.e("打印path" ,path); final File file=new File(path); new Thread(){ public void run () { try { AndroidUploadFile.uploadFile(file.getAbsolutePath(), "http://" +Host+":8080/PortalSystemAdmin/mobile/uploadfile" ); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }; }.start(); }catch (Exception e){e.printStackTrace();} }else { Log.e("onActivityResult" ,"intent.getData()回调数据为空!!!!!!" ); } } break ; } } }
运行结果以及总结 途中遇到的问题和解决方案 实体类无法转化json问题 开始视频上传是能成功的,但是android端接受不到请求返回的json消息,并且总是会报406错误 然而回去看,代码里确实是有 @ResponseBody注解的,这个注解就是实体类转化为json回传给android端 结果仔细检查后发现主要是自己的json依赖包没有导入(卒) 然后在springmvc.xml中加一句:
1 <mvc:annotation-driven />
之后再在lib目录下导入jackson-annotations-2.9.8.jar、jackson-core-2.9.8.jar、jackson-databind-2.9.8.jar这3个依赖包后解决406问题
同样的依赖路径存在多个 遇到的报错: More than one file was found with OS independent path ‘META-INF/DEPENDENCIES’ 添加如下代码后,报错消失:
1 2 3 4 5 6 7 android { ... packagingOptions { exclude 'META-INF/DEPENDENCIES' } }
结果截图
参考博客 博主 molly Hu 的springmvc服务端+android客户端的文件上传
博主 zhangphil 的Android Stduio报错:More than one file was found with OS independent path ‘META-INF/DEPENDENCIES’