博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android 中 webview 上传图片后,图片文件失去后缀的问题
阅读量:2718 次
发布时间:2019-05-13

本文共 7699 字,大约阅读时间需要 25 分钟。

在webview中选择图片一般是设置WebChromeClient,然后重写openFileChooser方法,最后在onActivityResult中得到图片Uri

问题来了,这个Uri一般都没有文件后缀(.jpg.png),像下面这样

filecontent://media/external/images/media/68987

将图片上传到服务器后,保存在服务器的文件名字就是68987了,文件没有后缀,将后缀改为.jpg之后,图片是正确的,,,

遇到这个问题排查了一天

解决方式

根据 Uri 获取文件的真实路径, 然后再把真实路径转成 Uri. 这时候的 Uri 就是带文件真实名和后缀的.

// 根据 Uri 获取文件真实路径的代码:
https://gist.github.com/atearsan/1f0846e6dcdb3d8f3d1d

// 真实路径转成 Uri 的代码: Uri.fromFile(new File(filePath));

// Uri 打印结果: file:///storage/emulated/0/DCIM/Camera/IMG_20151006_193049.jpg

// 根据 Uri 获取文件真实路径的代码

package com.atearsan.util;import android.annotation.TargetApi;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;// Code taken from: http://stackoverflow.com/questions/20067508/get-real-path-from-uri-android-kitkat-new-storage-access-frameworkpublic class MediaUtility {    /**     * Get a file path from a Uri. This will get the the path for Storage Access     * Framework Documents, as well as the _data field for the MediaStore and     * other file-based ContentProviders.     *     * @param context The context.     * @param uri     The Uri to query.     * @author paulburke     */    @TargetApi(Build.VERSION_CODES.KITKAT)    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());    }}

 

 

以下做一下科普:

 

一、URI 

  通用资源标志符(Universal Resource Identifier, 简称"URI")。

  Uri代表要操作的数据,Android上可用的每种资源 - 图像、视频片段等都可以用Uri来表示。

  URI一般由三部分组成:

    访问资源的命名机制。 

    存放资源的主机名。 

    资源自身的名称,由路径表示。 

  Android的Uri由以下三部分组成: "content://"、数据的路径、标示ID(可选)

  举些例子,如: 

    所有联系人的Uri: content://contacts/people

    某个联系人的Uri: content://contacts/people/5

    所有图片Uri: content://media/external

    某个图片的Uri:content://media/external/images/media/4

 

  二、内部保存

  首先我们来看一下android是如何管理多媒体文件(音频、视频、图片)的信息。通过DDMS,我们在/data/data/com.android.providers.media下找到数据库文件

  

  打开external.db文件进一步查看:在media表格下,可以看到文件路径(_data)和Uri的标示ID(_id)的对应关系。

  

  三、相互转换

   1.从URI获得文件路径

   

 

1     string  myImageUrl = "content://media/external/images/media/***"; 2     Uri uri = Uri.parse(myImageUrl); 3      4  5     String[] proj = { MediaStore.Images.Media.DATA };    6     Cursor actualimagecursor = this.ctx.managedQuery(uri,proj,null,null,null);   7     int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);    8     actualimagecursor.moveToFirst();    9     10 11     String img_path = actualimagecursor.getString(actual_image_column_index);  12     File file = new File(img_path);13     Uri fileUri = Uri.fromFile(file);

 

 

 

  2.由文件路径得到URI

1             Uri mUri = Uri.parse("content://media/external/images/media");  2             Uri mImageUri = null; 3  4             Cursor cursor = managedQuery( 5                     MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, 6                     null, MediaStore.Images.Media.DEFAULT_SORT_ORDER); 7             cursor.moveToFirst(); 8  9             while (!cursor.isAfterLast()) {10                 String data = cursor.getString(cursor11                         .getColumnIndex(MediaStore.MediaColumns.DATA));12                 if (picPath.equals(data)) {13                     int ringtoneID = cursor.getInt(cursor14                             .getColumnIndex(MediaStore.MediaColumns._ID));15                     mImageUri = Uri.withAppendedPath(mUri, ""16                             + ringtoneID);17                     break;18                 }19                 cursor.moveToNext();20             }

 

 

转载地址:http://dlktd.baihongyu.com/

你可能感兴趣的文章
实例解读Docker Swarm
查看>>
Eclipse 4.16 稳定版发布
查看>>
Abp 代码生成器使用说明
查看>>
Odoo 14 版本优化更新的新功能体验
查看>>
从容器开始的良好做法
查看>>
使用HTML5创建和播放声音
查看>>
SpecFlow的力量
查看>>
使用Swagger,ApiExplorer和NSwag掌握ASP.NET Core和ABP中的外部Web API
查看>>
使用Entity Developer构建ASP.NET Core Web API应用程序
查看>>
动态构建LINQ表达式
查看>>
使用ASP.NET Web API和Handlebars的Web模板
查看>>
PowerToys 0.19.0 发布,微软开发的免费实用工具集
查看>>
华为正式开源数据虚拟化引擎 openLooKeng
查看>>
机器学习的三种方法
查看>>
使用ASP.NET Web API和Handlebars的Web模板
查看>>
微服务中的面向切面编程和更多模式
查看>>
十多位全球技术专家,为你献上近十个小时的.Net微服务介绍
查看>>
用于打开和创建SQLite,Microsoft SQL Server,PostgreSQL和MySQL SQL数据库的WPF对话框
查看>>
在Visual Studio中使用C#脚本(CSX脚本)生成代码
查看>>
检查和变异可查询表达式树
查看>>