แปลงไฟล์: Uri เป็น File ใน Android


401

วิธีที่ง่ายที่สุดในการแปลงจาก a file: android.net.Uriเป็น a Fileใน Android คืออะไร?

พยายามต่อไปนี้ แต่ใช้งานไม่ได้:

 final File file = new File(Environment.getExternalStorageDirectory(), "read.me");
 Uri uri = Uri.fromFile(file);
 File auxFile = new File(uri.toString());
 assertEquals(file.getAbsolutePath(), auxFile.getAbsolutePath());

นี่คือทางออกของฉัน !! มันใช้งานได้ดี! stackoverflow.com/questions/2789276/…
cesards


assertEquals ทำอะไร?
Huzaifa Asif

Uri.from บริบทไฟล์ไม่ทำงานกับฉัน :(
เบย์

คำตอบ:


781

สิ่งที่คุณต้องการคือ ...

new File(uri.getPath());

... และไม่...

new File(uri.toString());

หมายเหตุ: uri.toString()ผลตอบแทนสตริงในรูปแบบ: "file:///mnt/sdcard/myPicture.jpg"ในขณะที่ผลตอบแทนสตริงในรูปแบบ:uri.getPath()"/mnt/sdcard/myPicture.jpg"


4
ความแตกต่างระหว่างสองคืออะไร? อะไรtoStringทำอย่างไร
Merlyn Morgan-Graham

86
url.toString()ส่งคืนสตริงในรูปแบบต่อไปนี้: "ไฟล์: ///mnt/sdcard/myPicture.jpg" ในขณะที่url.getPath()ส่งคืนสตริงในรูปแบบต่อไปนี้: "/mnt/sdcard/myPicture.jpg" เช่นไม่มีประเภทแผนผังที่กำหนดไว้ล่วงหน้า - แก้ไขแล้ว.
Adil Hussain

44
หาก URI นั้นเป็น Images.Media.EXTERNAL_CONTENT_URI (เช่นจาก Intent.ACTION_PICK สำหรับแกลเลอรี่) จากคุณคุณจะต้องค้นหาในstackoverflow.com/q/6935497/42619
Nuthatch

2
@Chlebta ตรวจสอบห้องสมุดชื่อPicassoสำหรับการโหลดไฟล์ (แม้กระทั่ง URL) ลงใน ImageViews ได้อย่างง่ายดายมาก
Virat Singh

18
เวลาส่วนใหญ่ที่ฉันได้รับopen failed: ENOENT (No such file or directory)เมื่อฉันพยายามเปิดไฟล์ที่ให้มาด้วยสิ่งนี้ นอกจากนี้หาก Uri เป็น Content Uri ของรูปภาพมันจะไม่ทำงานอย่างแน่นอน
clu

50

หลังจากค้นหามานานแล้วนี่คือสิ่งที่ใช้ได้ผลสำหรับฉัน:

File file = new File(getPath(uri));


public String getPath(Uri uri) 
    {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
        if (cursor == null) return null;
        int column_index =             cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String s=cursor.getString(column_index);
        cursor.close();
        return s;
    }

6
managedQueryเลิกใช้แล้ว ใช้getContentResolver().query(...)แทนซึ่งใช้งานได้กับ API 11+ เพิ่มเงื่อนไขสำหรับอุปกรณ์ที่เก่ากว่า API 11
Kyle Falconer

2
สิ่งนี้ส่งคืน null ให้ฉันด้วยเหตุผลบางอย่าง และ android uri ของฉันกลับมาเหมือน: {content: //com.android.providers.media.documents/document/image%3A2741} Android.Net.UriInvoker
erkinyldz

มันไม่ได้เป็นทางออกที่ดีเพราะมันจะไม่ทำงานในทุกแพลตฟอร์ม อุปกรณ์บางอย่างไม่ได้เติมคอลัมน์นี้ฉันขอแนะนำให้ผู้ให้บริการเนื้อหาจัดการสิ่งนี้ตามที่แนะนำโดย @CommonWare ในคำตอบก่อนหน้า
Liran Cohen

3
ไฟล์นี้เป็นไฟล์ประเภทภาพเท่านั้นแล้วคนอื่น ๆ ล่ะ?
Pratibha sarve

2
ตรวจสอบให้แน่ใจว่าคุณได้รับ uri จาก Intent.ACTION_PICK และไม่ได้ตั้งใจ ACTION_GET_CONTENT เพราะในภายหลังไม่มี MediaStore.Images.Media.DATA
Denys Lobur

34

ใช้

InputStream inputStream = getContentResolver().openInputStream(uri);    

โดยตรงและคัดลอกไฟล์ ดูเพิ่มเติมที่:

https://developer.android.com/guide/topics/providers/document-provider.html


1
นี้ควร upvoted มากขึ้น ContentResolver เป็นสิ่งที่ดูเหมือนว่าคุณจะดูตามค่าเริ่มต้นเพื่อแก้ไขเส้นทางจาก Android.Net.Uri
Mike Makarov

ฉันต้องการเพิ่มอีกโหวต แต่ปรากฎว่าฉันสามารถทำได้เพียงครั้งเดียว!
Xenolion

27

แก้ไข: ขออภัยฉันควรทดสอบดีขึ้นมาก่อน สิ่งนี้น่าจะใช้ได้:

new File(new URI(androidURI.toString()));

URI คือ java.net.URI


3
อ่า แต่คำถามคือ Uri ไม่ใช่ URI ผู้คนต้องระวังสิ่งนั้น :)
Muz

1
@Muz ฉันเชื่อว่าคำตอบนั้นถูกต้อง androidURIคือ android.net.Uri java.net.URI (ซึ่งมีอยู่บน Android) ใช้เป็นส่วนหนึ่งของกระบวนการแปลงเท่านั้น
Matthew Flaschen

2
เราไม่สามารถทำได้เพียง: ไฟล์ใหม่ (uri.getPath ());
Bart Burg

14
นี่เป็นเพียงการโยน: IllegalArgumentException: รูปแบบไฟล์ที่คาดหวังใน URI: เนื้อหา: // media / external / images / media / 80038
Jacek Kwiecień

7
ฉันได้รับการjava.lang.IllegalArgumentException: Expected file scheme in URI: content://com.shajeel.daily_monitoring.localstorage.documents.localstorage.documents/document/%2Fstorage%2Femulated%2F0%2FBook1.xlsxยกเว้นหลังจากใช้วิธีนี้
Shajeel Afzal

15

ทางออกที่ดีที่สุด

สร้างหนึ่งคลาส FileUtil อย่างง่ายและใช้สร้างคัดลอกและเปลี่ยนชื่อไฟล์

ฉันใช้uri.toString()แล้วuri.getPath()แต่ไม่ได้ผลกับฉัน ในที่สุดฉันก็พบวิธีนี้

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FileUtil {
    private static final int EOF = -1;
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

    private FileUtil() {

    }

    public static File from(Context context, Uri uri) throws IOException {
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        String fileName = getFileName(context, uri);
        String[] splitName = splitFileName(fileName);
        File tempFile = File.createTempFile(splitName[0], splitName[1]);
        tempFile = rename(tempFile, fileName);
        tempFile.deleteOnExit();
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(tempFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (inputStream != null) {
            copy(inputStream, out);
            inputStream.close();
        }

        if (out != null) {
            out.close();
        }
        return tempFile;
    }

    private static String[] splitFileName(String fileName) {
        String name = fileName;
        String extension = "";
        int i = fileName.lastIndexOf(".");
        if (i != -1) {
            name = fileName.substring(0, i);
            extension = fileName.substring(i);
        }

        return new String[]{name, extension};
    }

    private static String getFileName(Context context, Uri uri) {
        String result = null;
        if (uri.getScheme().equals("content")) {
            Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
            try {
                if (cursor != null && cursor.moveToFirst()) {
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
        if (result == null) {
            result = uri.getPath();
            int cut = result.lastIndexOf(File.separator);
            if (cut != -1) {
                result = result.substring(cut + 1);
            }
        }
        return result;
    }

    private static File rename(File file, String newName) {
        File newFile = new File(file.getParent(), newName);
        if (!newFile.equals(file)) {
            if (newFile.exists() && newFile.delete()) {
                Log.d("FileUtil", "Delete old " + newName + " file");
            }
            if (file.renameTo(newFile)) {
                Log.d("FileUtil", "Rename file to " + newName);
            }
        }
        return newFile;
    }

    private static long copy(InputStream input, OutputStream output) throws IOException {
        long count = 0;
        int n;
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        while (EOF != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }
}

ใช้คลาส FileUtil ในรหัสของคุณ

try {
         File file = FileUtil.from(MainActivity.this,fileUri);
         Log.d("file", "File...:::: uti - "+file .getPath()+" file -" + file + " : " + file .exists());

  } catch (IOException e) {
          e.printStackTrace();
  }

มันใช้งานได้ แต่เมื่อฉันเลือกภาพจากแกลเลอรี่มันจะพ่นข้อผิดพลาดในบรรทัด: InputStream inputStream = context.getContentResolver (). openInputStream (uri);
Vahid Akbari

มันทำงานได้ดีมาก แต่มันก็พ่น FileNotFoundException บนอุปกรณ์ Android บางตัว
vishwajit76

มันไม่ทำงานกับกล้อง
suyash saurabh

ใช้รหัสนี้เพื่อเลือกภาพถ่ายจากกล้องstackoverflow.com/a/51095098/7008132
vishwajit76

13

สิ่งนี้ไม่ได้ผลสำหรับฉัน ฉันพบว่านี่เป็นวิธีแก้ปัญหาการทำงาน แต่กรณีของฉันเป็นเฉพาะกับภาพ

String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();

นี่ควรเป็นคำตอบ! :) ฉันทดสอบกับ API 25
iroiroys

4
โปรดทราบว่าเทคนิคนี้ถูกแบนใน Android Q. คุณไม่สามารถเข้าถึงคอลัมน์ DATA ได้อีกต่อไป (ซึ่งเป็นวิธีที่ไม่น่าเชื่อถือตั้งแต่แรก)
CommonsWare

13

Android + Kotlin

  1. เพิ่มการพึ่งพาสำหรับส่วนขยาย Kotlin Android:

    implementation 'androidx.core:core-ktx:{latestVersion}'

  2. รับไฟล์จาก uri:

    uri.toFile()

Android + Java

เพียงเลื่อนไปด้านบน;)


3
ใช้งานได้เฉพาะในกรณีที่รูปแบบ uri ถูกตั้งค่าเป็นfile
MatPag


2

@CommonsWare อธิบายทุกสิ่งค่อนข้างดี และเราควรใช้วิธีแก้ปัญหาที่เขาเสนอ

โดยวิธีการเฉพาะข้อมูลที่เราสามารถพึ่งพาเมื่อสอบถามContentResolverเป็นชื่อและขนาดของไฟล์ดังกล่าวที่นี่: การดึงข้อมูลไฟล์ | นักพัฒนา Android

ดังที่คุณเห็นว่ามีอินเทอร์เฟซOpenableColumnsที่มีเพียงสองฟิลด์: DISPLAY_NAME และ SIZE

ในกรณีของฉันฉันต้องดึงข้อมูล EXIF ​​เกี่ยวกับภาพ JPEG และหมุนหากจำเป็นก่อนที่จะส่งไปยังเซิร์ฟเวอร์ ในการทำเช่นนั้นฉันได้คัดลอกเนื้อหาไฟล์ไปเป็นไฟล์ชั่วคราวโดยใช้ContentResolverและopenInputStream()


1

ฉันทำสิ่งนี้ตามวิธีต่อไปนี้:

try {
    readImageInformation(new File(contentUri.getPath()));

} catch (IOException e) {
    readImageInformation(new File(getRealPathFromURI(context,
                contentUri)));
}

public static String getRealPathFromURI(Context context, Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver().query(contentUri, proj,
                null, null, null);
        int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
}

โดยพื้นฐานแล้วก่อนอื่นฉันลองใช้ไฟล์เช่นภาพที่ถ่ายด้วยกล้องและบันทึกไว้ในการ์ด SD สิ่งนี้ใช้ไม่ได้กับรูปภาพที่ส่งคืนโดย: Intent photoPickerIntent = Intent ใหม่ (Intent.ACTION_PICK); กรณีนั้นมีความจำเป็นต้องแปลง Uri ให้เป็นเส้นทางจริงตามgetRealPathFromURI()หน้าที่ ดังนั้นข้อสรุปคือมันขึ้นอยู่กับชนิดของ Uri ที่คุณต้องการแปลงเป็นไฟล์


1

หากคุณมีUriที่สอดคล้องกับแล้วคุณอาจไม่ต้องการที่จะใช้DocumentContract Fileหากคุณอยู่ในคอตลินใช้DocumentFileในการทำสิ่งที่คุณต้องการในโลกเก่าใช้Fileและใช้ContentResolverเพื่อรับสตรีม

ทุกอย่างอื่นรับประกันสวยที่จะทำลาย


0

สำหรับกรณีนี้โดยเฉพาะอย่างยิ่งบน Android วิธีที่ใช้เป็นไบต์มักจะเร็วกว่า

ด้วยสิ่งนี้ฉันแก้ไขได้โดยการตั้งค่าคลาสFileHelperที่ได้รับความรับผิดชอบในการจัดการกับการอ่าน / เขียนไบต์จาก / ถึงไฟล์ผ่านสตรีมและคลาสUriHelperที่ให้ความรับผิดชอบในการหาเส้นทางของ Uri และการอนุญาต

เท่าที่รู้โดยทั่วไป string.getBytes((charset == null) ? DEFAULT_CHARSET:charset)สามารถช่วยให้เราถ่ายโอนสตริงที่คุณต้องการเป็นไบต์ที่คุณต้องการ

วิธีให้ UriHelper และ FileHelper ให้คุณคัดลอกรูปภาพที่ Uri จดไว้ในไฟล์คุณสามารถเรียกใช้:

FileHelper.getInstance().copy(UriHelper.getInstance().toFile(uri_of_a_picture)
                        , FileHelper.getInstance().createExternalFile(null, UriHelper.getInstance().generateFileNameBasedOnTimeStamp()
                                + UriHelper.getInstance().getFileName(uri_of_a_picture, context), context)
                );

เกี่ยวกับ UriHelper ของฉัน:

public class UriHelper {
private static UriHelper INSTANCE = new UriHelper();

public static UriHelper getInstance() {
    return INSTANCE;
}

@SuppressLint("SimpleDateFormat")
public String generateFileNameBasedOnTimeStamp() {
    return new SimpleDateFormat("yyyyMMdd_hhmmss").format(new Date()) + ".jpeg";
}

/**
 * if uri.getScheme.equals("content"), open it with a content resolver.
 * if the uri.Scheme.equals("file"), open it using normal file methods.
 */
//

public File toFile(Uri uri) {
    if (uri == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    return new File(uri.getPath());
}

public DocumentFile toDocumentFile(Uri uri) {
    if (uri == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    return DocumentFile.fromFile(new File(uri.getPath()));
}

public Uri toUri(File file) {
    if (file == null) return null;
    Logger.d(">>> file path:" + file.getAbsolutePath());
    return Uri.fromFile(file); //returns an immutable URI reference representing the file
}

public String getPath(Uri uri, Context context) {
    if (uri == null) return null;
    if (uri.getScheme() == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    String path;
    if (uri.getScheme().equals("content")) {
        //Cursor cursor = context.getContentResolver().query(uri, new String[] {MediaStore.Images.ImageColumns.DATA}, null, null, null);
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor == null) {
            Logger.e("!!! cursor is null");
            return null;
        }
        if (cursor.getCount() >= 0) {
            Logger.d("... the numbers of rows:" + cursor.getCount()
                        + "and the numbers of columns:" + cursor.getColumnCount());
            if (cursor.isBeforeFirst()) {
                while (cursor.moveToNext()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                }
            } else {
                cursor.moveToFirst();
                do {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                } while (cursor.moveToNext());
            }
            path = uri.getPath();
            cursor.close();
            Logger.d("... content scheme:" + uri.getScheme() + "  and return:" + path);
            return path;
        } else {
            path = uri.getPath();
            Logger.d("... content scheme:" + uri.getScheme()
                    + " but the numbers of rows in the cursor is < 0:" + cursor.getCount()
                    + "  and return:" + path);
            return path;
        }
    } else {
        path = uri.getPath();
        Logger.d("... not content scheme:" + uri.getScheme() + "  and return:" + path);
        return path;
    }
}

public String getFileName(Uri uri, Context context) {
    if (uri == null) return null;
    if (uri.getScheme() == null) return null;
    Logger.d(">>> uri path:" + uri.getPath());
    Logger.d(">>> uri string:" + uri.toString());
    String path;
    if (uri.getScheme().equals("content")) {
        //Cursor cursor = context.getContentResolver().query(uri, new String[] {MediaStore.Images.ImageColumns.DATA}, null, null, null);
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor == null) {
            Logger.e("!!! cursor is null");
            return null;
        }
        if (cursor.getCount() >= 0) {
            Logger.d("... the numbers of rows:" + cursor.getCount()
                    + "and the numbers of columns:" + cursor.getColumnCount());
            if (cursor.isBeforeFirst()) {
                while (cursor.moveToNext()) {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                }
            } else {
                cursor.moveToFirst();
                do {
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i<cursor.getColumnCount(); i++) {
                        stringBuilder.append("... iterating cursor.getString(" + i +"(" + cursor.getColumnName(i) + ")):" + cursor.getString(i));
                        stringBuilder.append("\n");
                    }
                    Logger.d(stringBuilder.toString());
                } while (cursor.moveToNext());
            }
            cursor.moveToFirst();
            path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME));
            cursor.close();
            Logger.d("... content scheme:" + uri.getScheme() + "  and return:" + path);
            return path;
        } else {
            path = uri.getLastPathSegment();
            Logger.d("... content scheme:" + uri.getScheme()
                    + " but the numbers of rows in the cursor is < 0:" + cursor.getCount()
                    + "  and return:" + path);
            return path;
        }
    } else {
        path = uri.getLastPathSegment();
        Logger.d("... not content scheme:" + uri.getScheme() + "  and return:" + path);
        return path;
    }
}

}

เกี่ยวกับ FileHelper ของฉัน:

public class FileHelper {
private static final String DEFAULT_DIR_NAME = "AmoFromTaiwan";
private static final int DEFAULT_BUFFER_SIZE = 1024;
private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private static final int EOF = -1;
private static FileHelper INSTANCE = new FileHelper();

public static FileHelper getInstance() {
    return INSTANCE;
}

private boolean isExternalStorageWritable(Context context) {
    /*
    String state = Environment.getExternalStorageState();
    return Environment.MEDIA_MOUNTED.equals(state);
    */
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (context.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            Logger.e("!!! checkSelfPermission() not granted");
            return false;
        }
    } else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}

private boolean isExternalStorageReadable(Context context) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (context.checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            Logger.e("!!! checkSelfPermission() not granted");
            return false;
        }
    } else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}

@SuppressLint("SimpleDateFormat")
private String generateFileNameBasedOnTimeStamp() {
    return new SimpleDateFormat("yyyyMMdd_hhmmss").format(new Date()) + ".jpeg";
}

public File createExternalFile(String dir_name, String file_name, Context context) {
    String dir_path;
    String file_path;
    File dir ;
    File file;
    if (!isExternalStorageWritable(context)) {
        Logger.e("!!! external storage not writable");
        return null;
    }
    if (dir_name == null) {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + DEFAULT_DIR_NAME;
    } else {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + dir_name;
    }
    Logger.d("... going to access an external dir:" + dir_path);
    dir = new File(dir_path);
    if (!dir.exists()) {
        Logger.d("... going to mkdirs:" + dir_path);
        if (!dir.mkdirs()) {
            Logger.e("!!! failed to mkdirs");
            return null;
        }
    }
    if (file_name == null) {
        file_path = dir_path + File.separator + generateFileNameBasedOnTimeStamp();
    } else {
        file_path = dir_path + File.separator + file_name;
    }
    Logger.d("... going to return an external dir:" + file_path);
    file = new File(file_path);
    if (file.exists()) {
        Logger.d("... before creating to delete an external dir:" + file.getAbsolutePath());
        if (!file.delete()) {
            Logger.e("!!! failed to delete file");
            return null;
        }
    }
    return file;
}

public File createInternalFile(String dir_name, String file_name, Context context) {
    String dir_path;
    String file_path;
    File dir ;
    File file;
    if (dir_name == null) {
        dir = new ContextWrapper(context).getDir(DEFAULT_DIR_NAME, Context.MODE_PRIVATE);
    } else {
        dir = new ContextWrapper(context).getDir(dir_name, Context.MODE_PRIVATE);
    }
    dir_path = dir.getAbsolutePath();
    Logger.d("... going to access an internal dir:" + dir_path);
    if (!dir.exists()) {
        Logger.d("... going to mkdirs:" + dir_path);
        if (!dir.mkdirs()) {
            Logger.e("!!! mkdirs failed");
            return null;
        }
    }
    if (file_name == null) {
        file = new File(dir, generateFileNameBasedOnTimeStamp());
    } else {
        file = new File(dir, file_name);
    }
    file_path = file.getAbsolutePath();
    Logger.d("... going to return an internal dir:" + file_path);
    if (file.exists()) {
        Logger.d("... before creating to delete an external dir:" + file.getAbsolutePath());
        if (!file.delete()) {
            Logger.e("!!! failed to delete file");
            return null;
        }
    }
    return file;
}

public File getExternalFile(String dir_name, String file_name, Context context) {
    String dir_path;
    String file_path;
    File file;
    if (!isExternalStorageWritable(context)) {
        Logger.e("!!! external storage not writable");
        return null;
    }
    if (dir_name == null) {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + DEFAULT_DIR_NAME;
    } else {
        dir_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + File.separator + dir_name;
    }
    if (file_name == null) {
        file_path = dir_path;
    } else {
        file_path = dir_path + File.separator + file_name;
    }
    Logger.d("... going to return an external file:" + file_path);
    file = new File(file_path);
    if (file.exists()) {
        Logger.d("... file exists:" + file.getAbsolutePath());
    } else {
        Logger.e("!!! file does't exist:" + file.getAbsolutePath());
    }
    return file;
}

public File getInternalFile(String dir_name, String file_name, Context context) {
    String file_path;
    File dir ;
    File file;
    if (dir_name == null) {
        dir = new ContextWrapper(context).getDir(DEFAULT_DIR_NAME, Context.MODE_PRIVATE);
    } else {
        dir = new ContextWrapper(context).getDir(dir_name, Context.MODE_PRIVATE);
    }
    if (file_name == null) {
        file = new File(dir.getAbsolutePath());
    } else {
        file = new File(dir, file_name);
    }
    file_path = file.getAbsolutePath();
    Logger.d("... going to return an internal dir:" + file_path);
    if (file.exists()) {
        Logger.d("... file exists:" + file.getAbsolutePath());
    } else {
        Logger.e("!!! file does't exist:" + file.getAbsolutePath());
    }
    return file;
}

private byte[] readBytesFromFile(File file) {
    Logger.d(">>> path:" + file.getAbsolutePath());
    FileInputStream fis;
    long file_length;
    byte[] buffer;
    int offset = 0;
    int next = 0;
    if (!file.exists()) {
        Logger.e("!!! file doesn't exists");
        return null;
    }
    if (file.length() > Integer.MAX_VALUE) {
        Logger.e("!!! file length is out of max of int");
        return null;
    } else {
        file_length = file.length();
    }
    try {
        fis = new FileInputStream(file);
        //buffer = new byte[(int) file_length];
        buffer = new byte[(int) file.length()];
        long time_start = System.currentTimeMillis();
        while (true) {
            Logger.d("... now next:" + next + " and offset:" + offset);
            if (System.currentTimeMillis() - time_start > 1000) {
                Logger.e("!!! left due to time out");
                break;
            }
            next = fis.read(buffer, offset, (buffer.length-offset));
            if (next < 0 || offset >= buffer.length) {
                Logger.d("... completed to read");
                break;
            }
            offset += next;
        }
        //if (offset < buffer.length) {
        if (offset < (int) file_length) {
            Logger.e("!!! not complete to read");
            return null;
        }
        fis.close();
        return buffer;
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return null;
    }
}

public byte[] readBytesFromFile(File file, boolean is_fis_fos_only) {
    if (file == null) return null;
    if (is_fis_fos_only) {
        return readBytesFromFile(file);
    }
    Logger.d(">>> path:" + file.getAbsolutePath());
    FileInputStream fis;
    BufferedInputStream bis;
    ByteArrayOutputStream bos;
    byte[] buf = new byte[(int) file.length()];
    int num_read;
    if (!file.exists()) {
        Logger.e("!!! file doesn't exists");
        return null;
    }
    try {
        fis = new FileInputStream(file);
        bis = new BufferedInputStream(fis);
        bos = new ByteArrayOutputStream();
        long time_start = System.currentTimeMillis();
        while (true) {
            if (System.currentTimeMillis() - time_start > 1000) {
                Logger.e("!!! left due to time out");
                break;
            }
            num_read = bis.read(buf, 0, buf.length); //1024 bytes per call
            if (num_read < 0) break;
            bos.write(buf, 0, num_read);
        }
        buf = bos.toByteArray();
        fis.close();
        bis.close();
        bos.close();
        return buf;
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        Logger.e("!!! FileNotFoundException");
        return null;
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return null;
    }
}

/**
 * streams (InputStream and OutputStream) transfer binary data
 * if to write a string to a stream, must first convert it to bytes, or in other words encode it
 */
public boolean writeStringToFile(File file, String string, Charset charset) {
    if (file == null) return false;
    if (string == null) return false;
    return writeBytesToFile(file, string.getBytes((charset == null) ? DEFAULT_CHARSET:charset));
}

public boolean writeBytesToFile(File file, byte[] data) {
    if (file == null) return false;
    if (data == null) return false;
    FileOutputStream fos;
    BufferedOutputStream bos;
    try {
        fos = new FileOutputStream(file);
        bos = new BufferedOutputStream(fos);
        bos.write(data, 0, data.length);
        bos.flush();
        bos.close();
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return false;
    }
    return true;
}

/**
 * io blocks until some input/output is available.
 */
public boolean copy(File source, File destination) {
    if (source == null || destination == null) return false;
    Logger.d(">>> source:" + source.getAbsolutePath() + ", destination:" + destination.getAbsolutePath());
    try {
        FileInputStream fis = new FileInputStream(source);
        FileOutputStream fos = new FileOutputStream(destination);
        byte[] buffer = new byte[(int) source.length()];
        int len;
        while (EOF != (len = fis.read(buffer))) {
            fos.write(buffer, 0, len);
        }
        if (true) { //debug
            byte[] copies = readBytesFromFile(destination);
            if (copies != null) {
                int copy_len = copies.length;
                Logger.d("... stream read and write done for " + copy_len + " bytes");
            }
        }
        return destination.length() != 0;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

public void list(final String path, final String end, final List<File> files) {
    Logger.d(">>> path:" + path + ", end:" + end);
    File file = new File(path);
    if (file.isDirectory()) {
        for (File child : file.listFiles()){
            list(child.getAbsolutePath(), end, files);
        }
    } else if (file.isFile()) {
        if (end.equals("")) {
            files.add(file);
        } else {
            if (file.getName().endsWith(end)) files.add(file);
        }
    }
}

public String[] splitFileName(File file, String split) {
    String path;
    String ext;
    int lastIndexOfSplit = file.getAbsolutePath().lastIndexOf(split);
    if (lastIndexOfSplit < 0) {
        path = file.getAbsolutePath();
        ext = "";
    } else {
        path = file.getAbsolutePath().substring(0, lastIndexOfSplit);
        ext = file.getAbsolutePath().substring(lastIndexOfSplit);
    }
    return new String[] {path, ext};
}

public File rename(File old_file, String new_name) {
    if (old_file == null || new_name == null) return null;
    Logger.d(">>> old file path:" + old_file.getAbsolutePath() + ", new file name:" + new_name);
    File new_file = new File(old_file, new_name);
    if (!old_file.equals(new_file)) {
        if (new_file.exists()) { //if find out previous file/dir at new path name exists
            if (new_file.delete()) {
                Logger.d("... succeeded to delete previous file at new abstract path name:" + new_file.getAbsolutePath());
            } else {
                Logger.e("!!! failed to delete previous file at new abstract path name");
                return null;
            }
        }
        if (old_file.renameTo(new_file)) {
            Logger.d("... succeeded to rename old file to new abstract path name:" + new_file.getAbsolutePath());
        } else {
            Logger.e("!!! failed to rename old file to new abstract path name");
        }
    } else {
        Logger.d("... new and old file have the equal abstract path name:" + new_file.getAbsolutePath());
    }
    return new_file;
}

public boolean remove(final String path, final String end) {
    Logger.d(">>> path:" + path + ", end:" + end);
    File file = new File(path);
    boolean result = false;
    if (file.isDirectory()) {
        for (File child : file.listFiles()){
            result = remove(child.getAbsolutePath(), end);
        }
    } else if (file.isFile()) {
        if (end.equals("")) {
            result = file.delete();
        } else {
            if (file.getName().endsWith(end)) result = file.delete();
        }
    } else {
        Logger.e("!!! child is not file or directory");
    }
    return result;
}

@TargetApi(Build.VERSION_CODES.O)
public byte[] readNIOBytesFromFile(String path) throws IOException {
    Logger.d(">>> path:" + path);
    if (!Files.exists(Paths.get(path), LinkOption.NOFOLLOW_LINKS)) {
        Logger.e("!!! file doesn't exists");
        return null;
    } else {
        return Files.readAllBytes(Paths.get(path));
    }
}

@TargetApi(Build.VERSION_CODES.O)
public File writeNIOBytesToFile(String dir, String name, byte[] data) {
    Logger.d(">>> dir:" + dir + ", name:" + name);
    Path path_dir;
    Path path_file;
    try {
        if (!Files.exists(Paths.get(dir), LinkOption.NOFOLLOW_LINKS)) {
            Logger.d("... make a dir");
            path_dir = Files.createDirectories(Paths.get(dir));
            if (path_dir == null) {
                Logger.e("!!! failed to make a dir");
                return null;
            }
        }
        path_file = Files.write(Paths.get(name), data);
        return path_file.toFile();
    } catch (IOException e) {
        e.printStackTrace();
        Logger.e("!!! IOException");
        return null;
    }
}

@TargetApi(Build.VERSION_CODES.O)
public void listNIO(final String dir, final String end, final List<File> files) throws IOException {
    Logger.d(">>> dir:" + dir + ", end:" + end);
    Files.walkFileTree(Paths.get(dir), new FileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
            Logger.d("... file:" + dir.getFileName());
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
            Logger.d("... file:" + file.getFileName());
            if (end.equals("")) {
                files.add(file.toFile());
            } else {
                if (file.endsWith(end)) files.add(file.toFile());
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) {
            Logger.d("... file:" + file.getFileName());
            if (end.equals("")) {
                files.add(file.toFile());
            } else {
                if (file.endsWith(end)) files.add(file.toFile());
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
            Logger.d("... file:" + dir.getFileName());
            return FileVisitResult.CONTINUE;
        }
    });
}

/**
 * recursion
 */
private int factorial (int x) {
    if (x > 1) return (x*(factorial(x-1)));
    else if (x == 1) return x;
    else return 0;
}

}


-1

สำหรับคนที่อยู่ที่นี่กำลังมองหาทางออกสำหรับภาพโดยเฉพาะที่นี่มันเป็น

private Bitmap getBitmapFromUri(Uri contentUri) {
        String path = null;
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null);
        if (cursor.moveToFirst()) {
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            path = cursor.getString(columnIndex);
        }
        cursor.close();
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        return bitmap;
    }

-1

ไฟล์ imageToUpload = ไฟล์ใหม่ (ใหม่ URI (androidURI.toString ())); ใช้งานได้ถ้าเป็นไฟล์ที่คุณสร้างขึ้นในที่จัดเก็บข้อมูลภายนอก

ตัวอย่างไฟล์: /// ที่เก็บข้อมูล / จำลอง / 0 / (บางไดเรกทอรีและชื่อไฟล์)


-1

ประชาชน String getRealPathFromURI (Uri uri) {

    String result;
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor == null) {
        result = uri.getPath();
        cursor.close();
        return result;
    }
    cursor.moveToFirst();
    int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
    result = cursor.getString(idx);
    cursor.close();
    return result;
}

จากนั้นใช้เพื่อรับไฟล์จาก URI:

        File finalFile = newFile(getRealPathFromURI(uri));

- ทั้งสามารถช่วยคุณได้ ----


1
โปรดทราบว่าเทคนิคนี้ถูกแบนใน Android Q. คุณไม่สามารถเข้าถึงคอลัมน์ DATA ได้อีกต่อไป (ซึ่งเป็นวิธีที่ไม่น่าเชื่อถือตั้งแต่แรก)
CommonsWare

-1

จากรหัสต่อไปนี้ฉันสามารถรับไฟล์ adobe แอปพลิเคชันที่แชร์เป็นกระแสและบันทึกลงในเส้นทางแอปพลิเคชัน Android

Android.Net.Uri fileuri =
    (Android.Net.Uri)Intent.GetParcelableExtra(Intent.ExtraStream);

    fileuri i am getting as {content://com.adobe.reader.fileprovider/root_external/
                                        data/data/com.adobe.reader/files/Downloads/sample.pdf}

    string filePath = fileuri.Path;

   filePath I am gettings as root_external/data/data/com.adobe.reader/files/Download/sample.pdf

      using (var stream = ContentResolver.OpenInputStream(fileuri))
      {
       byte[] fileByteArray = ToByteArray(stream); //only once you can read bytes from stream second time onwards it has zero bytes

       string fileDestinationPath ="<path of your destination> "
       convertByteArrayToPDF(fileByteArray, fileDestinationPath);//here pdf copied to your destination path
       }
     public static byte[] ToByteArray(Stream stream)
        {
            var bytes = new List<byte>();

            int b;
            while ((b = stream.ReadByte()) != -1)
                bytes.Add((byte)b);

            return bytes.ToArray();
        }

      public static string convertByteArrayToPDF(byte[] pdfByteArray, string filePath)
        {

            try
            {
                Java.IO.File data = new Java.IO.File(filePath);
                Java.IO.OutputStream outPut = new Java.IO.FileOutputStream(data);
                outPut.Write(pdfByteArray);
                return data.AbsolutePath;

            }
            catch (System.Exception ex)
            {
                return string.Empty;
            }
        }

-2

ส่วนขยายพื้นฐานของ @Jacek Kwiecieńคำตอบสำหรับการแปลงภาพ uriเป็นไฟล์

fun Uri.toImageFile(context: Context): File? {
    val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
    val cursor = context.contentResolver.query(this, filePathColumn, null, null, null)
    if (cursor != null) {
        if (cursor.moveToFirst()) {
            val columnIndex = cursor.getColumnIndex(filePathColumn[0])
            val filePath = cursor.getString(columnIndex)
            cursor.close()
            return File(filePath)
        }
        cursor.close()
    }
    return null
}

ถ้าเราใช้File(uri.getPath())มันจะไม่ทำงาน

ป้อนคำอธิบายรูปภาพที่นี่

หากเราใช้ส่วนขยายจากandroid-ktxก็ยังใช้งานไม่ได้เพราะ https://github.com/android/android-ktx/blob/master/src/main/java/androidx/core/net/Uri.kt


2
โปรดทราบว่าเทคนิคนี้ถูกแบนใน Android Q. คุณไม่สามารถเข้าถึงDATAคอลัมน์ได้อีกต่อไป(ซึ่งเป็นวิธีที่ไม่น่าเชื่อถือตั้งแต่แรก)
CommonsWare

-2

เพิ่มเข้าonActivityResultรับไฟล์ docx หรือ pdf

var imageUriPath = ""
imageUriPath =
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    val split = (imageUri.path ? : "").split(":") //split the path.
    split[1]
  } else {
    imageUri.path ? : ""
  }
val file = File(imageUriPath)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.