Android 通过form表单上传文字,图片,视频等(通过key值)以及问题分析

Android 通过form表单上传文字,图片,视频等(通过key值)以及问题分析

最近做到上传的时候,弄了一段时间,也遇到了一些问题和解决方案,在这里就和大家分享一下,希望对你们有用,谢谢。

好了,思想+代码

上传类Java代码:

/**
 * Created by aierJun on 2017/3/9.
 */
public class UploadUtils {
    private static String BOUNDARY = UUID.randomUUID().toString();  //边界标识   随机生成
    private static String PREFIX = "--", LINE_END = "\r\n";
    private static String CONTENT_TYPE = "multipart/form-data";   //内容类型
    private static final String TAG = "uploadFile";
    private static final int TIME_OUT = 10 * 1000;   //超时时间
    private static final String CHARSET = "utf-8"; //设置编码
    private static  int state;
    /**
     * @category 上传文件至Server的方法
     * @param uploadUrl 上传路径参数
     * @author ylbf_dev
     */
    public static boolean uploadFile(final ArrayList<File> imagefiles,final ArrayList<File> videofiles, final String uploadUrl,final ArrayList<String> name,final ArrayList<Object> values) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    URL url = new URL(uploadUrl);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setReadTimeout(TIME_OUT);
                    conn.setConnectTimeout(TIME_OUT);
                    conn.setDoInput(true);  //允许输入流
                    conn.setDoOutput(true); //允许输出流
                    conn.setUseCaches(false);  //不允许使用缓存
                    conn.setRequestMethod("POST");  //请求方式
                    conn.setRequestProperty("Charset", CHARSET);  //设置编码
                    conn.setRequestProperty("connection", "keep-alive");
                    conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY);

                    DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
                    StringBuffer sb = new StringBuffer();

                    sb.append(PREFIX);
                    sb.append(BOUNDARY);
                    sb.append(LINE_END);
                    /**
                     * 这里重点注意:
                     * name里面的值为服务器端需要key   只有这个key 才可以得到对应的文件
                     * filename是文件的名字,包含后缀名的   比如:abc.png
                     */
                    if (name!=null&&name.size()>0)
                        for (int i=0;i<name.size();i++){
                            addText(name.get(i),values.get(i)+"",dos);
                        }
                    addImage(imagefiles,dos);
                    addVedio(videofiles,dos);

                    // 读取服务器返回结果
                    InputStream isBack = conn.getInputStream();
                    InputStreamReader isr = new InputStreamReader(isBack, "utf-8");
                    BufferedReader br = new BufferedReader(isr);
                    String result = br.readLine();
                    Log.d("Jun",result);
                    dos.close();
                    JSONObject jsonObject =new JSONObject(result);
                    state=jsonObject.optInt("State");
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }).start();
        if (state==1){
            return true;
        }else{
            return false;
        }

    }
    private static void addText(String name,Object value,DataOutputStream output) {
        StringBuilder sb = new StringBuilder();
        sb.append(PREFIX  + BOUNDARY + LINE_END);
        sb.append("Content-Disposition: form-data; name=\""+name+"\"" + LINE_END);
        sb.append(LINE_END);
        sb.append(value + LINE_END);
        sb.append(PREFIX + BOUNDARY + LINE_END);
        try {
            output.writeBytes(sb.toString());// 发送表单字段数据
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static void addImage(ArrayList<File> files, DataOutputStream output) {
        if (files.size()<1||files==null) return;
            try {
                StringBuilder sb = new StringBuilder();
                sb.append(PREFIX + BOUNDARY + LINE_END);
                sb.append("Content-Disposition: form-data; name=\"image\"; filename=\"" + files.get(0).getName() + "\"" + LINE_END);
                sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END);
                sb.append(LINE_END);
                output.write(sb.toString().getBytes());
                InputStream is = new FileInputStream(files.get(0));
                byte[] bytes = new byte[1024];
                int len = 0;
                Log.d("Jun","开始上传");
                while ((len = is.read(bytes)) != -1) {
                    output.write(bytes, 0, len);
                }
                is.close();
                output.write(LINE_END.getBytes());
                byte[] end_data = (PREFIX + BOUNDARY  + LINE_END).getBytes();
                output.write(end_data);
            }catch (Exception e){
                throw new RuntimeException(e);
            }
    }
    private static void addVedio(ArrayList<File> files, DataOutputStream output) {
        if (files==null||files.size()<1) return;
        try {
            StringBuilder sb = new StringBuilder();
            sb.append(PREFIX + BOUNDARY + LINE_END);
            sb.append("Content-Disposition: form-data; name=\"video\"; filename=\"" + files.get(0).getName() + "\"" + LINE_END);
            sb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END);
            sb.append(LINE_END);
            output.write(sb.toString().getBytes());
            InputStream is = new FileInputStream(files.get(0));
            byte[] bytes = new byte[1024];
            int len = 0;
            final int headerSize = sb.length();
            Log.d("Jun","开始上传");
            while ((len = is.read(bytes)) != -1) {
                output.write(bytes, 0, len);
            }
            is.close();
            output.write(LINE_END.getBytes());
            byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes();
            output.write(end_data);
            Log.d("Jun",output+"");
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

}
注意:上面的为封装方法。有text,Image,video。
对上面的分析在下面的问题里会有说明。

java调用方法:

    public   ArrayList<File> files=new ArrayList<>();
    private  ArrayList<String> names=new ArrayList<>();
    private  ArrayList<Object> values=new ArrayList<>();
//添加数据
boolean state=UploadUtils.uploadFile(files,null, APIManger.PUSH_STORY, names, values);
注意这里的添加数据name和values是一一对应的关系,小心数据乱了name.add()后values.add();或者再用Arraylist,保证对应就行。

遇到的问题分析:

一.text可以上传,image可以上传,但video不能上传
1.起初,我调试的时候发现视频总是服务器端接收不到,但后,我把image的添加给注销掉了,用video直接上传,发现视频是可以上传的,但就是一起不能实现,然后debug
2.这里写图片描述
3.这里写图片描述
4.这里写图片描述
5.这里写图片描述
6,最后问题找到了,开始标签和结束标签的问题。修改为上面的图4和图5,好了。一般的开始–xxx,结束–xxx,最后一次的开始–xxx,结束–xxx–,注意换行我省略了。
二,视频选取和视频路径不是绝对的问题
1,image解决方法
 Uri uri = data.getData();
                    Cursor cursor = PushVedioActivity.this.getContentResolver().query(uri, null, null, null, null);
                    cursor.moveToFirst();
                    String imgNo = cursor.getString(0); // 图片编号
                    String imgPath = cursor.getString(1); // 图片文件路径
                    filesImage.add(new File(imgPath));
                    String imgSize = cursor.getString(2); // 图片大小
                    String imgName = cursor.getString(3); // 图片文件名
                    cursor.close();
2,最终完美解决方案
/**
 * Created by aierJun on 2017/3/13.
 */
public class UriAllUriUtils {

        /**
         * 专为Android4.4设计的从Uri获取文件绝对路径,以前的方法已不好使
         */
        @SuppressLint("NewApi")
        public static String getPath(final Context context, final Uri uri) {

            final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

            // DocumentProvider
            if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];

                    if ("primary".equalsIgnoreCase(type)) {
                        return Environment.getExternalStorageDirectory() + "/" + split[1];
                    }

                    // TODO handle non-primary volumes
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri)) {

                    final String id = DocumentsContract.getDocumentId(uri);
                    final Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                    return getDataColumn(context, contentUri, null, null);
                }
                // MediaProvider
                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] };

                    return getDataColumn(context, contentUri, selection, selectionArgs);
                }
            }
            // MediaStore (and general)
            else if ("content".equalsIgnoreCase(uri.getScheme())) {
                return getDataColumn(context, uri, null, null);
            }
            // File
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }

            return null;
        }

        /**
         * Get the value of the data column for this Uri. This is useful for
         * MediaStore Uris, and other file-based ContentProviders.
         *
         * @param context
         *            The context.
         * @param uri
         *            The Uri to query.
         * @param selection
         *            (Optional) Filter used in the query.
         * @param selectionArgs
         *            (Optional) Selection arguments used in the query.
         * @return The value of the _data column, which is typically a file path.
         */
        public 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;
        }

        /**
         * @param uri
         *            The Uri to check.
         * @return Whether the Uri authority is ExternalStorageProvider.
         */
        public static boolean isExternalStorageDocument(Uri uri) {
            return "com.android.externalstorage.documents".equals(uri.getAuthority());
        }

        /**
         * @param uri
         *            The Uri to check.
         * @return Whether the Uri authority is DownloadsProvider.
         */
        public static boolean isDownloadsDocument(Uri uri) {
            return "com.android.providers.downloads.documents".equals(uri.getAuthority());
        }

        /**
         * @param uri
         *            The Uri to check.
         * @return Whether the Uri authority is MediaProvider.
         */
        public static boolean isMediaDocument(Uri uri) {
            return "com.android.providers.media.documents".equals(uri.getAuthority());
        }
}
注意:封装方法
三,文字text编码格式问题
/**
 * Created by aierJun on 2017/3/13.
 */
public class GetFormStringUTF8Utils {
    public static String getUTF8String(String string){
        String s=null;
            try {
                s=  new String(string.getBytes("UTF-8"),"ISO8859-1");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        return s;
    }
}
注意:封装方法

编码详细请点击此连接

以上,为个人上传的总结,希望对你们有用,如有错误和误解请指教,谢谢。

如需转载,请注明出处http://blog.csdn.net/aierJun/article/details/61916699,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值