从Uri创建文件

时间:2017-08-05 09:59:19

标签: android

我试图将图片上传到php,因为我需要将文件发送到服务器。所以我试图从data参数创建一个文件。

但我收到此错误Cannot resolve constructor File

这是我的代码:

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
            // Get the url from data
            Uri selectedImageUri = data.getData();
            if (null != selectedImageUri) {
                // File
                File imageFilePath = new File(selectedImageUri);

5 个答案:

答案 0 :(得分:14)

适当的方法是getContentResolver().openInputStream(uri_of_your_file);并使用FileOutputStream到您想要的路径,然后使用该文件。

Commonsware answer

开始
  

您可以使用ContentResolver和openInputStream()来获取   由Uri表示的内容上的InputStream。你可以创建一个   您控制的某个文件上的FileOutputStream。而且,您可以使用Java   要从InputStream复制到OutputStream的I / O,制作自己的   您控制的文件中的内容副本。

执行此操作的示例代码,

InputStream in =  getContentResolver().openInputStream("your_uri_here");
OutputStream out = new FileOutputStream(new File("your_file_here"));
        byte[] buf = new byte[1024];
        int len;
        while((len=in.read(buf))>0){
            out.write(buf,0,len);
        }
        out.close();
        in.close();

答案 1 :(得分:4)

@GeekDroid's答案是正确的,但我想我会提供更多信息以帮助澄清。

I've also created a library that will return the file path from an Uri when selecting a File from MediaStore.


我创建了一个类,该类将在您的应用程序目录内复制/创建一个新文件。这是在后台线程上完成的,应该这样做。

我还创建了一个回调接口来获取“状态”并显示 $table->increments('id'); $table->integer('user_id')->unique()->unsigned(); $table->integer('store_id')->unique()->unsigned(); $table->timestamps(); $table->foreign('user_id') ->references('id') ->on('users') ->onDelete('cascade'); $table->foreign('store_id') ->references('id') ->on('storeinfos') ->onDelete('cascade'); $user=User::create($request->except(['store_id'])); } catch (\Exception $exception) { logger()->error($exception); return redirect()->back()->with('message', 'Unable to create new user.'); } CatererUser::create([ 'user_id' => $user->id, 'store_id' =>$request->input('store_id'), ]);

这里是接口(您可以将名称和回调更改为任何内容):

ProgressBar

这是复制文件的类:

interface CallBackTask {
    void onCopyPreExecute();
    void onCopyProgressUpdate(int progress);
    void onCopyPostExecute(String path, boolean wasSuccessful, String reason);
}

在您的public class CopyFileAsyncTask extends AsyncTask<Uri, Integer, String> { private Uri mUri; private CallBackTask callback; private WeakReference<Context> mContext; private String pathPlusName; private File folder; private Cursor returnCursor; private InputStream is = null; private String errorReason = ""; DownloadAsyncTask(Uri uri, Context context, CallBackTask callback) { this.mUri = uri; mContext = new WeakReference<>(context); this.callback = callback; } @Override protected void onPreExecute() { callback.onCopyPreExecute(); Context context = mContext.get(); if (context != null) { folder = context.getExternalFilesDir("Temp"); returnCursor = context.getContentResolver().query(mUri, null, null, null, null); try { is = context.getContentResolver().openInputStream(mUri); } catch (FileNotFoundException e) { e.printStackTrace(); } } } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); int post = values[0]; callback.onCopyProgressUpdate(post); } @Override protected String doInBackground(Uri... params) { File file = null; int size = -1; try { try { if (returnCursor != null && returnCursor.moveToFirst()){ if (mUri.getScheme() != null) if (mUri.getScheme().equals("content")) { int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE); size = (int) returnCursor.getLong(sizeIndex); }else if (mUri.getScheme().equals("file")) { File ff = new File(mUri.getPath()); size = (int) ff.length(); } } } finally { if (returnCursor != null) returnCursor.close(); } pathPlusName = folder + "/" + getFileName(mUri, mContext.get()); file = new File(folder + "/" + getFileName(mUri, mContext.get())); BufferedInputStream bis = new BufferedInputStream(is); FileOutputStream fos = new FileOutputStream(file); byte[] data = new byte[1024]; long total = 0; int count; while ((count = bis.read(data)) != -1) { if (!isCancelled()) { total += count; if (size != -1) { publishProgress((int) ((total * 100) / size)); } fos.write(data, 0, count); } } fos.flush(); fos.close(); } catch (IOException e) { errorReason = e.getMessage(); } return file.getAbsolutePath(); } private String getFileName(Uri uri, Context context) { String result = null; if (uri.getScheme() != null) { if (uri.getScheme().equals("content")) { Cursor cursor = context.getContentResolver().query(uri, null, null, null, null); if (cursor != null && cursor.moveToFirst()) { result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)); } if (cursor != null) { cursor.close(); } } } if (result == null) { result = uri.getPath(); assert result != null; int cut = result.lastIndexOf('/'); if (cut != -1) { result = result.substring(cut + 1); } } return result; } protected void onPostExecute(String result) { if(result == null){ callback.onCopyPostExecute(pathPlusName, false, errorReason); }else { callback.onCopyPostExecute(pathPlusName, true, ""); } } } 中,您应该执行以下操作:

Activity

您可以随时通过以下方式取消文件的复制:

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class ExampleActivity extends AppCompatActivity implements CallBackTask{
    Button someBtn;
    Uri someUri = .... //This is just an example, you should provide your own Uri

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);

        someBtn = findViewById(R.id.someBtn);

        someBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                CopyFileAsyncTask asyntask = new CopyFileAsyncTask(someUri, ExampleActivity.this, ExampleActivity.this);
                asyntask.execute();
            }
        });

    }
    
    ProgressBar mProgressBar;
    TextView percentText;
    private AlertDialog mdialog;

    @Override
    public void onCopyPreExecute() {
        final AlertDialog.Builder mPro = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.myDialog));
        @SuppressLint("InflateParams") final View mPView = LayoutInflater.from(this).inflate(R.layout.dailog_layout, null);
        percentText = mPView.findViewById(R.id.percentText);

        mProgressBar = mPView.findViewById(R.id.mProgressBar);
        mProgressBar.setMax(100);
        mPro.setView(mPView);
        mdialog = mPro.create();
        mdialog.show();
    }

    @Override
    public void onCopyProgressUpdate(int progress) {
        String progressPlusPercent = progress + "%";
        percentText.setText(progressPlusPercent);
        mProgressBar.setProgress(progress);
    }

    @Override
    public void onCopyPostExecute(String path, boolean wasSuccessful, String reason) {
        if (mdialog != null && mdialog.isShowing()) {
            mdialog.cancel();
        }

        if (wasSuccessful){
            Toast.makeText(this, "File was created at - "+path, Toast.LENGTH_SHORT).show();
        }else{
            Toast.makeText(this, "Error - "+reason, Toast.LENGTH_SHORT).show();
        }
        
    }
}

如果要完全按照我的方式实施它,并在复制文件时显示if (asyntask!=null){ asyntask.cancel(true); } ,那么这是对话框的布局和样式:

ProgressBar

R.style.myDialog

<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="myDialog" parent="Theme.AppCompat.Dialog.Alert"> <item name="android:windowNoTitle">true</item> <item name="android:background">#fff</item> <item name="android:windowBackground">@null</item> <item name="android:windowFrame">@null</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimEnabled">true</item> </style> </resources>

R.layout.dailog_layout

在复制文件时,出现以下对话框:

example


结论:

使用上述方法,您的文件将被复制到<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:id="@+id/loadContent" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:padding="20dp"> <RelativeLayout android:id="@+id/dotRel" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/percentText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginBottom="15dp" android:text="0 %" android:textColor="@android:color/black" android:textSize="25sp" /> <ProgressBar android:id="@+id/mProgressBar" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="5dp" android:layout_below="@+id/percentText" android:progressDrawable="@drawable/progressbar" /> </RelativeLayout> </RelativeLayout> </RelativeLayout> 。复制文件时,将显示一个进度对话框,以百分比形式指示进度(这对于复制大文件很有用)。如果复制文件时出错,则将在/storage/emulated/0/Android/data/yourPackageName/files/Temp/YourFile.jpg

中提供原因。

这将与文件和内容Uri一起使用。

答案 2 :(得分:1)

解决您问题的一线解决方案

File imageFile = new File(selectedImageUri.getPath());

你错过了

.getPath()

答案 3 :(得分:0)

您可以使用此功能从 uri 获取文件:

fun getFileFromUri(uri: Uri): File? {
    if (uri.path == null) {
        return null
    }
    var realPath = String()
    val databaseUri: Uri
    val selection: String?
    val selectionArgs: Array<String>?
    if (uri.path!!.contains("/document/image:")) {
        databaseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        selection = "_id=?"
        selectionArgs = arrayOf(DocumentsContract.getDocumentId(uri).split(":")[1])
    } else {
        databaseUri = uri
        selection = null
        selectionArgs = null
    }
    try {
        val column = "_data"
        val projection = arrayOf(column)
        val cursor = context.contentResolver.query(
            databaseUri,
            projection,
            selection,
            selectionArgs,
            null
        )
        cursor?.let {
            if (it.moveToFirst()) {
                val columnIndex = cursor.getColumnIndexOrThrow(column)
                realPath = cursor.getString(columnIndex)
            }
            cursor.close()
        }
    } catch (e: Exception) {
        Log.i("GetFileUri Exception:", e.message ?: "")
    }
    val path = if (realPath.isNotEmpty()) realPath else {
        when {
            uri.path!!.contains("/document/raw:") -> uri.path!!.replace(
                "/document/raw:",
                ""
            )
            uri.path!!.contains("/document/primary:") -> uri.path!!.replace(
                "/document/primary:",
                "/storage/emulated/0/"
            )
            else -> return null
        }
    }
    return File(path)
}

答案 4 :(得分:-3)

你可以试试这个;

try {
                Uri uri = data.getData();
                String selectedFilePath = FilePath.getPath(getActivity(), uri);
                final File file = new File(selectedFilePath);

                new UploadFileToServer().execute(file);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

并像这样定义FilePath类;

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;

 public class FilePath {

/**
 * Method for return file path of Gallery image/ Document / Video / Audio
 *
 * @param context
 * @param uri
 * @return path of the selected image file from gallery
 */
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());
}
}