【问题标题】:How can I pass URI to API using AsyncTask in Android/Java?如何在 Android/Java 中使用 AsyncTask 将 URI 传递给 API?
【发布时间】:2020-10-27 00:56:26
【问题描述】:

我正在尝试使用以下方法通过 Web API 发送 PDF 文件:

public static <function> JSONObject uploadFile(String url, Context context, JSONObject jsondata, String imagepath) {
        sJsonObj = null;
        sb = null;

        try {
            sUrl = new URL(url);

            sHttpUrlConnection = (HttpURLConnection) sUrl.openConnection();
            sHttpUrlConnection.setDoInput(true);
            sHttpUrlConnection.setDoOutput(true);
            sHttpUrlConnection.setUseCaches(false);
            sHttpUrlConnection.setReadTimeout(sTimeout);
            sHttpUrlConnection.setConnectTimeout(sTimeout);
            sHttpUrlConnection.setRequestMethod(HttpPost.METHOD_NAME);
            sHttpUrlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + BOUNDARY);
            sHttpUrlConnection.setRequestProperty("fileName", imagepath);
            sHttpUrlConnection.setRequestProperty("Connection", "Keep-Alive");


            sPrintWriter = new PrintWriter(sHttpUrlConnection.getOutputStream());

            sPrintWriter.append(TWO_HYPHENS + BOUNDARY)
                    .append(LINE_END)
                    .append("Content-Disposition: form-data;name=\"body\"")
                    .append(LINE_END)
                    .append(LINE_END)
                    .append(jsondata.toString())
                    .append(LINE_END)

                    .append(TWO_HYPHENS + BOUNDARY)
                    .append(LINE_END)
                    .append("Content-Disposition: form-data; name=\"fileName\"; filename=\"" + new File(imagepath).getAbsoluteFile() + "\"")
                    .append(LINE_END)
                    .append("Content-Type: "
                            + URLConnection.guessContentTypeFromName(imagepath))
                    .append(LINE_END)
                    .append("Content-Transfer-Encoding: binary")
                    .append(LINE_END)
                    .append(LINE_END);

            sPrintWriter.flush();

            FileInputStream fileStream = new FileInputStream(imagepath);
            byte[] buffer = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = fileStream.read(buffer)) != -1) {
                sHttpUrlConnection.getOutputStream().write(buffer, 0, bytesRead);
            }

            fileStream.close();

            sPrintWriter.append(LINE_END);
            sPrintWriter.append(TWO_HYPHENS);
            sPrintWriter.append(BOUNDARY);
            sPrintWriter.append(TWO_HYPHENS);
            sPrintWriter.flush();
            sHttpUrlConnection.getOutputStream().close();

            if (true) {
                BufferedReader reader = null;
                reader = new BufferedReader(new InputStreamReader(sHttpUrlConnection.getInputStream()));
                sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
                reader.close();

                sJsonObj = new JSONObject(sb.toString());
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sHttpUrlConnection.disconnect();
        }
        return sJsonObj;
    }

如果你仔细看uploadFile方法的参数,你会发现最后一个参数是filePath

在Stack Overflow上连续2天搜索后,我发现在某些较新的Android版本中我无法获取filePath。

而且我的应用支持Api level 21到30,所以大家都建议只通过传递URI试试。

现在,在这个 uploadFile 方法中,如果我尝试将最后一个参数从 String 更改为 Uri,那么很多地方都会出现编译器错误。现在我不明白我应该在这个方法中改变什么?

任何人都可以用相同的方法发布一些修改的答案,这将非常感激。

FileNotFound 异常即将到来,如果我将通过 uri.getPath

【问题讨论】:

    标签: java android android-asynctask


    【解决方案1】:

    你可以试试吗?我提供了一些代码:

    public static String getPath(final Context context, final Uri uri) {
    
        // check here to KITKAT or new version
        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];
                }
            }
            // 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.
     */
    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;
    }
    
    /**
     * @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());
    }
    
    /**
     * @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());
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 2013-02-15
    • 1970-01-01
    • 2015-06-16
    • 2013-07-13
    相关资源
    最近更新 更多