文件上传路径错误:应用运行正常但上传图片时崩溃
Hey there, let's break down why your app is crashing when uploading images, and fix those issues step by step based on the code snippets you shared:
MediaStore.Images.Media.DATA Deprecation & Scoped Storage Conflict Starting with Android 10 (API 29), the MediaStore.Images.Media.DATA column is deprecated, and direct file path access is restricted by Scoped Storage. This is almost certainly causing your cursor to return null for that column, leading to a NullPointerException or IllegalStateException when you try to fetch the string.
Fix: Use ContentResolver to access the image directly via stream
Instead of relying on a file path, open an input stream from the image's Uri. This works across all Android versions and avoids Scoped Storage issues:
// Replace your cursor path fetching code with this Uri imageUri = ...; // The Uri you got from the gallery/file picker InputStream imageStream = getContentResolver().openInputStream(imageUri);
You can pass this stream directly to your multipart upload (more on that below).
getPath() Method Most custom getPath() implementations break on Android 10+ or when dealing with content:// Uris (the standard format from modern file pickers). If this method returns null or an invalid path, your upload will crash when it tries to access a non-existent file.
Fix: Either deprecate getPath() or update it for compatibility
If you absolutely need a file path (not recommended for modern Android), use this version that handles legacy and newer OS versions:
public String getPath(Context context, Uri uri) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // For Android Q+, we can't get a direct path—use stream instead return null; } // Legacy handling for Android 9 and below String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); if (cursor == null) return null; int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String path = cursor.getString(columnIndex); cursor.close(); return path; }
But again—using an input stream is the more reliable approach for modern apps.
uploadMultipart() Crash Triggers If your upload method expects a valid file path but gets null, or tries to read a file that doesn't exist, it'll throw exceptions like FileNotFoundException or NullPointerException.
Fix: Update uploadMultipart() to use input streams
Here's a revised example using OkHttp (a common library for multipart uploads) that works with input streams instead of file paths:
private void uploadMultipart(InputStream imageStream, String fileName) { OkHttpClient client = new OkHttpClient(); // Build the multipart request using the stream RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart( "image", fileName, RequestBody.create(MediaType.parse("image/jpeg"), imageStream) ) .build(); Request request = new Request.Builder() .url("your_upload_api_endpoint") // Replace with your actual URL .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // Handle upload failure (e.g., show error to user) e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { // Handle successful upload (e.g., parse response) String responseData = response.body().string(); } else { // Handle server-side error } } }); }
Bonus: Get the file name from the Uri
To pass a valid file name to the upload method, use this helper:
private String getFileNameFromUri(Context context, Uri uri) { String fileName = null; if ("content".equals(uri.getScheme())) { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null) { cursor.moveToFirst(); fileName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME)); cursor.close(); } } // Fallback to extracting name from path if needed if (fileName == null) { fileName = uri.getLastPathSegment(); } return fileName; }
Always check your Logcat for the exact crash exception (e.g., NullPointerException, SecurityException). This will tell you exactly which line is failing and why—critical for narrowing down edge cases.
内容的提问来源于stack exchange,提问作者Ash Hickey

