当前位置: 首页 > 知识库问答 >
问题:

无法将照片从相机上传到服务器。IllegalArgumentException:列“_data”不存在

宗政洋
2023-03-14

我无法将相机拍摄的照片发送到服务器。我一步一步地遵循了谷歌关于拍照的文档(https://developer.android.com/training/camera/photoBasics),但仍然无法做到这一点。从设备库上传文件似乎很好。另外,如果我录制了一个视频,上传将是美味的。

这是我的活动代码:

private static int REQUEST_IMAGE_CAPTURE = 2;

private String mCurrentPhotoPath;

private Uri photoUri;

private List<File> filesArray;
private List<Uri> filesUrisArray;
private List<String> mimeTypesArray;

// Camera Intent
public void takePhoto() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            photoUri = null;
            try {
                photoFile = createImageFile();
                photoUri = FileProvider.getUriForFile(this, "com.company.name.appname.provider", photoFile);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            // Continue only if the File was successfully created
            if (photoUri != null) {
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
            }
        }
    }
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode){
            case 2:
                if (resultCode == RESULT_OK) {
                    try {
                        galleryAddPic();
                        filesUrisArray.set(selectedMedia, photoUri);
                        mimeTypesArray.set(selectedMedia, getContentResolver().getType(photoUri));
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                break;
        }

    }
/**
 * Add the photo to gallery
 */
private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}
 /**
 * Method to create image file name (usado cuando sacas fotos con la cámara)
 */
private File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "PNG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".png",    /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.getAbsolutePath();

    return image;
}

文件提供程序:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.company.name.appname.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>
Caused by: java.lang.IllegalArgumentException: column '_data' does not exist. Available columns: []
        at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:340)
        at android.database.CursorWrapper.getColumnIndexOrThrow(CursorWrapper.java:87)
        at com.company.name.appname.comun.utils.FileUtils.getDataColumn(FileUtils.java:231)
        at com.company.name.appname.comun.utils.FileUtils.getPath(FileUtils.java:329)
        at com.company.name.appname.comun.utils.FileUtils.getFile(FileUtils.java:349)
@NonNull
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {  
    File file = FileUtils.getFile(this, fileUri);

    RequestBody requestFile =
        RequestBody.create(
            MediaType.parse(getContentResolver().getType(fileUri)), 
            file
        );

    return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
}   

FileUtils类(由方法getDataColumn引起的异常):

 /**
 * Convert Uri into File, if possible.
 *
 * @return file A local file that the Uri was pointing to, or null if the
 *         Uri is unsupported or pointed to a remote resource.
 * @see #getPath(Context, Uri)
 * @author paulburke
 */
public static File getFile(Context context, Uri uri) {
    if (uri != null) {
        String path = getPath(context, uri);
        if (path != null && isLocal(path)) {
            return new File(path);
        }
    }
    return null;
}
 /**
 * 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.<br>
 * <br>
 * Callers should check whether the path is local before assuming it
 * represents a local file.
 *
 * @param context The context.
 * @param uri The Uri to query.
 * @see #isLocal(String)
 * @see #getFile(Context, Uri)
 * @author paulburke
 */
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {

    if (DEBUG)
        Log.d(TAG + " File -",
                "Authority: " + uri.getAuthority() +
                        ", Fragment: " + uri.getFragment() +
                        ", Port: " + uri.getPort() +
                        ", Query: " + uri.getQuery() +
                        ", Scheme: " + uri.getScheme() +
                        ", Host: " + uri.getHost() +
                        ", Segments: " + uri.getPathSegments().toString()
        );

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

    // DocumentProvider
    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
        // LocalStorageProvider
        if (isLocalStorageDocument(uri)) {
            // The path is the id
            return DocumentsContract.getDocumentId(uri);
        }
        // ExternalStorageProvider
        else 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 the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        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.
 * @author paulburke
 */
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()) {
            if (DEBUG)
                DatabaseUtils.dumpCursor(cursor);

            // THIS IS WHERE THE CRASH OCCURS
            final int column_index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(column_index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}

共有1个答案

孟俊发
2023-03-14

您所需要的是在配置更改中保留MCurrentPhotoPath(或派生信息),例如将其放在保存的实例状态Bundle中。有关如何将action_image_captureextra_outputfileprovider一起使用的演示,请参见此示例项目,包括处理配置更改。

 类似资料:
  • 我是android studio和手机应用程序开发的初学者,但我仍在努力学习。因此,我设法构建了我的第一个webview应用程序来显示页面和图片。我发现了许多有用的资源来帮助我这样做,但我仍然面临着一个问题,即如何直接上传从手机摄像头(而不是从图库)拍摄的照片并上传到服务器。 1-在我按下眉毛按钮后,应用程序会提示我是从相机还是从画廊拍摄照片。(Android版9)2-当我从图库上传一张照片时,应

  • 问题内容: 我正在尝试从Android设备将文件上传到php服务器。有相同问题的话题,但他使用的是不同的方法。我的Android辅助代码运行正常,并且未显示任何错误消息,但服务器未收到任何文件。这是我的示例代码,我在网上找到了。 和我的PHP服务器端代码如下 Apache正在运行。当我运行服务器时,出现此错误消息。上传文件时出错,请重试!我已经在eclipse中检查了日志数据,我认为是套接字问题,

  • 上传拍下的照片、视频到服务器 > 原文链接 : Android Uploading Camera Image, Video to Server with Progress Bar 作者 : Ravi Tamada 译者 : chaossss 校对者: Mr.Simple 状态 : 校对完成 我在上一篇教程中给大家讲解了怎么通过进度条下载文件,今天,我将在这篇文章中给大家讲解如果在弹出进度条的同时上

  • 我试图构建一个,它包括两个按钮,一个用于用相机拍照并上传到Firebase存储,另一个用于从Firebase存储下载图像并在上显示。 现在,我被上传功能卡住了。我可以把照片保存到应用程序目录中。我想上传保存的图片到Firebase存储。

  • 我的MainActivity代码在这里:

  • 我已经处理了文件选择器,它完美地上传了文件, <罢工> 问题出在相机上。一旦我试图上传相机照片,它崩溃了。据我所知,这是因为URI。 a)文件选择器:内容://media/external/images/1234 b)摄像:文件:///mnt/sdcard/pic.jpg <罢工> 它现在崩溃了,因为在尝试上传“content://media/external/images/1234”时出现了nu