【问题标题】:java.io.FileNotFoundException caught when processing request: /document/raw:/storage/emulated/0/Download/mypdf.pdf (No such file or directory)java.io.FileNotFoundException 处理请求时捕获:/document/raw:/storage/emulated/0/Download/mypdf.pdf(没有这样的文件或目录)
【发布时间】:2018-03-08 14:22:14
【问题描述】:

我想使用多部分请求将 pdf 发送到我的服务器。我能够正确选择文件并获取其名称,但是当我发送此 pdf 时,我正在发送以下路径 /document/raw:/storage/emulated/0/Download/kitchenapp.pdf。路径是正确的,文件在那里,但我得到了这个异常。 I/DefaultRequestDirector: I/O exception (java.io.FileNotFoundException) caught when processing request: /document/raw:/storage/emulated/0/Download/kitchenapp.pdf (No such file or directory)

到目前为止我做了什么.. 通过这个获取 pdf

 Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("application/pdf");
    intent.addCategory(Intent.CATEGORY_OPENABLE);

    try {
        startActivityForResult(
                Intent.createChooser(intent, "Select a File to Upload"),
                1);
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(getActivity(), "Please install a File Manager.",
                Toast.LENGTH_SHORT).show();
    }

由此获取onActivity结果

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null) {
        Uri selectedFileURI = data.getData();
         file = new File(selectedFileURI.getPath().toString());
        Log.d("", "File : " + file.getName());
        String uploadedFileName = file.getName().toString();
        System.out.println("upload file name "+uploadedFileName);

        System.out.println("my location "+file);



    }
}

通过多部分请求发送此文件

  if (file != null ) {


                entity.addPart("file", new FileBody(file));
            }

            // totalSize = entity.getContentLength();
            httppost.setEntity(entity);

            // Making server call
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity r_entity = response.getEntity();

任何帮助将不胜感激..

【问题讨论】:

  • 您是否在 Manifest 中添加了权限?
  • 我已经声明了 API 23 或更高版本的清单和运行时权限,正如我所提到的,我也可以获取文件名。但我认为问题出在路径上。所以在上传时它的显示文件未找到异常。 @Ankita

标签: android pdf android-contentprovider filepath


【解决方案1】:

这些行帮助了我:

 if (isDownloadsDocument(uri)) {// DownloadsProvider
            final String id = DocumentsContract.getDocumentId(uri);
            if (!TextUtils.isEmpty(id)) {
                if (id.startsWith("raw:")) {
                    return id.replaceFirst("raw:", "");
                }
                try {
                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                    return getDataColumn(context, contentUri, null, null);
                } catch (NumberFormatException e) {
                    return null;
                }
            }
        }

【讨论】:

    【解决方案2】:

    我刚刚修复了代码 sn-p from this brilliant answer 中的 NumberFormat 崩溃。你可以通过代码here找到我的答案。

    【讨论】:

      【解决方案3】:

      我正在使用以下代码从 URI 获取路径:

      @Nullable
      public static String getPath(Context context, Uri uri) {
          // DocumentProvider
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && 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];
                  }
              } else if (isDownloadsDocument(uri)) {// DownloadsProvider
                  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);
      
              } else if (isMediaDocument(uri)) { // MediaProvider
                  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);
      
              }
          } else if ("content".equalsIgnoreCase(uri.getScheme())) {// MediaStore (and general)
              // Return the remote address
              if (isGooglePhotosUri(uri))
                  return uri.getLastPathSegment();
              return getDataColumn(context, uri, null, null);
      
          } else if ("file".equalsIgnoreCase(uri.getScheme())) {// File
              return uri.getPath();
          }
          return null;
      }
      
      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 index = cursor.getColumnIndexOrThrow(column);
                      return cursor.getString(index);
                  }
              } finally {
                  if (cursor != null)
                      cursor.close();
              }
              return null;
          }
      
          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());
          }
      
          /**
           * @param uri The Uri to check.
           * @return Whether the Uri authority is Google Photos.
           */
          public static boolean isGooglePhotosUri(Uri uri) {
              return "com.google.android.apps.photos.content".equals(uri.getAuthority());
          }
      

      onActivityResult() 方法中,您应该:

          @Override
          public void onActivityResult(int requestCode, int resultCode, Intent data) {
              // TODO Auto-generated method stub
              super.onActivityResult(requestCode, resultCode, data);
              if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null) {
                  Uri selectedFileURI = data.getData();
                  String fullPath = getPath(context, selectedFileURI);
                  file = new File(fullPath);
                  //.....
              }
          }
      

      记住:在您的 Manifest.xml 文件中声明读/写外部存储权限

      【讨论】:

      • 我已经尝试过该解决方案,但显示 java.lang.NumberFormatException: at final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long。 valueOf(id));
      • 我看了你的日志(/document/raw:/storage/emulated/0/Download/kitchenapp.pdf)。我认为更正后的路径是 /storage/emulated/0/Download/kitchenapp.pdf 。我不知道/document/raw: 是您添加的还是来自Uri ?你能发布完整的日志吗?你用哪个app来选择pdf文件?
      • 我在 Android Emulator Oreo API 26 中工作。我使用默认文件管理器来选择文件
      • 您提到的代码在 Lolipop 中运行良好。但在 KITKAT 中几乎没有修改。在 if 条件下它必须是这个(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT.. 而对于奥利奥它无法处理它。
      【解决方案4】:

      我认为您运行的是 Android 6.0 Marshmallow (API 23) 或更高版本。如果是这种情况,您必须在尝试读/写外部存储之前实现Runtime Permissions

      记住:-这仅在目标 SDK 为 23 或更高版本时有效。因此,在这种情况下,您已降级到 android APK 19 KitKat,然后它就可以正常工作了。并且还在您的 Android.Manifest 文件中声明读写权限。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多