จะแยกชื่อไฟล์จาก URI ที่ส่งคืนจาก Intent.ACTION_GET_CONTENT ได้อย่างไร


106

ฉันใช้ตัวจัดการไฟล์ของบุคคลที่สามเพื่อเลือกไฟล์ (PDF ในกรณีของฉัน) จากระบบไฟล์

นี่คือวิธีเปิดกิจกรรม:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(getString(R.string.app_pdf_mime_type));
intent.addCategory(Intent.CATEGORY_OPENABLE);

String chooserName = getString(R.string.Browse);
Intent chooser = Intent.createChooser(intent, chooserName);

startActivityForResult(chooser, ActivityRequests.BROWSE);

นี่คือสิ่งที่ฉันมีในonActivityResult:

Uri uri = data.getData();
if (uri != null) {
    if (uri.toString().startsWith("file:")) {
        fileName = uri.getPath();
    } else { // uri.startsWith("content:")

        Cursor c = getContentResolver().query(uri, null, null, null, null);

        if (c != null && c.moveToFirst()) {

            int id = c.getColumnIndex(Images.Media.DATA);
            if (id != -1) {
                fileName = c.getString(id);
            }
        }
    }
}

ข้อมูลโค้ดยืมมาจากคำแนะนำOpen Intents File Manager ที่มีอยู่ที่นี่:
http://www.openintents.org/en/node/829

จุดประสงค์if-elseคือความเข้ากันได้แบบย้อนกลับ ฉันสงสัยว่านี่เป็นวิธีที่ดีที่สุดในการรับชื่อไฟล์หรือไม่เนื่องจากฉันพบว่าตัวจัดการไฟล์อื่น ๆ ส่งคืนทุกสิ่ง

ตัวอย่างเช่นDocuments ToGo จะส่งคืนสิ่งต่อไปนี้:

content://com.dataviz.dxtg.documentprovider/document/file%3A%2F%2F%2Fsdcard%2Fdropbox%2FTransfer%2Fconsent.pdf

ซึ่งผลตอบแทนgetContentResolver().query() เพื่อให้สิ่งต่างๆน่าสนใจยิ่งขึ้นตัวจัดการไฟล์ที่ไม่มีชื่อ (ฉันได้รับ URI นี้จากบันทึกไคลเอนต์) ส่งคืนสิ่งที่ต้องการ:null

/./sdcard/downloads/.bin


มีวิธีที่ดีกว่าในการแยกชื่อไฟล์จาก URI หรือวิธีหนึ่งควรใช้การแยกวิเคราะห์สตริง


คำถามเดียวกันกับคำตอบที่ดีกว่า: stackoverflow.com/questions/8646246/…
Rémi

คำตอบ:


172

developer.android.com มีโค้ดตัวอย่างที่ดีสำหรับสิ่งนี้: https://developer.android.com/guide/topics/providers/document-provider.html

เวอร์ชันย่อเพื่อแยกชื่อไฟล์ (สมมติว่า "this" คือกิจกรรม):

public String getFileName(Uri uri) {
  String result = null;
  if (uri.getScheme().equals("content")) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    try {
      if (cursor != null && cursor.moveToFirst()) {
        result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
      }
    } finally {
      cursor.close();
    }
  }
  if (result == null) {
    result = uri.getPath();
    int cut = result.lastIndexOf('/');
    if (cut != -1) {
      result = result.substring(cut + 1);
    }
  }
  return result;
}

ในกรณีเมื่อคุณพยายามอ่าน MIMETYPE หรือชื่อไฟล์ของไฟล์จากกล้องแรกที่คุณต้องแจ้ง MediaScanner ที่จะแปลงURIของไฟล์ที่สร้างขึ้นของคุณจากfile://ไปcontent://ในonScanCompleted(String path, Uri uri)วิธีstackoverflow.com/a/5815005/2163045
Murt

10
การเพิ่มnew String[]{OpenableColumns.DISPLAY_NAME}เป็นพารามิเตอร์ที่สองในการสืบค้นจะกรองคอลัมน์สำหรับคำขอที่มีประสิทธิภาพมากขึ้น
JM Lord

OpenableColumns.DISPLAY_NAMEไม่ได้ผลสำหรับฉันฉันใช้MediaStore.Files.FileColumns.TITLEแทน
Dmitry Kopytov

สิ่งนี้จะขัดข้องสำหรับวิดีโอเมื่อสร้างเคอร์เซอร์ด้วยไฟล์ java.lang.IllegalArgumentException: Invalid column latitudeน่าเสียดาย ทำงานได้อย่างสมบูรณ์แบบสำหรับภาพถ่าย!
Lucas P.

ในทางเลือกอื่นคุณสามารถเรียกuri.getLastPathSegment()แทนที่จะแยกวิเคราะห์ด้วยตัวเอง
Grishka

45

ฉันกำลังใช้สิ่งนี้:

String scheme = uri.getScheme();
if (scheme.equals("file")) {
    fileName = uri.getLastPathSegment();
}
else if (scheme.equals("content")) {
    String[] proj = { MediaStore.Images.Media.TITLE };
    Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
    if (cursor != null && cursor.getCount() != 0) {
        int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE);
        cursor.moveToFirst();
        fileName = cursor.getString(columnIndex);
    }
    if (cursor != null) {
        cursor.close();
    }
}

4
ฉันได้ทำการทดสอบโค้ดของคุณแล้ว ใน URI ที่ส่งคืนโดย OI File Manager IllegalArgumentException จะถูกโยนเนื่องจากไม่มีคอลัมน์ 'title' บน URI ที่ยึดไว้โดยเคอร์เซอร์ Documents ToGo เป็นโมฆะ ใน URI ส่งคืนโดยโครงร่างตัวจัดการไฟล์ที่ไม่รู้จักคือโมฆะ
Viktor Brešan

2
อืมน่าสนใจ ใช่การทดสอบ Scheme! = null เป็นความคิดที่ดี อันที่จริงฉันไม่คิดว่า TITLE คือสิ่งที่คุณต้องการ ฉันใช้มันเพราะสื่อบางประเภทใน Android (เช่นเพลงที่เลือกผ่านเครื่องมือเลือกเพลง) มี URI เช่น content: // media / external / audio / media / 78 และฉันต้องการแสดงสิ่งที่เกี่ยวข้องมากกว่าหมายเลข ID คุณสามารถใช้ uri.getLastPathSegment () เช่นรหัสของฉันใช้สำหรับไฟล์: // URI หากคุณมี URI เช่นเนื้อหา: //...somefile.pdf
Ken Fehling

1
uri.getLastPathSegment (); - คุณได้บันทึกวันของฉันแล้ว :)
Lumis

@Ken Fehling: สิ่งนี้ไม่ได้ผลสำหรับฉัน ใช้งานได้เมื่อฉันคลิกไฟล์ในเบราว์เซอร์ไฟล์ แต่เมื่อฉันคลิกที่ไฟล์แนบอีเมลฉันยังคงได้รับเนื้อหา: // ... thing ฉันลองทำตามคำแนะนำทั้งหมดที่นี่โดยไม่มีโชค คิดว่าทำไม?
Luis A. Florit

1
สวัสดีทำไมcursorไม่close()d?
fikr4n

36

นำมาจากการดึงข้อมูลไฟล์ | นักพัฒนา Android

การเรียกชื่อไฟล์

private String queryName(ContentResolver resolver, Uri uri) {
    Cursor returnCursor =
            resolver.query(uri, null, null, null, null);
    assert returnCursor != null;
    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    returnCursor.moveToFirst();
    String name = returnCursor.getString(nameIndex);
    returnCursor.close();
    return name;
}

1
ฉันมองหาสิ่งนี้มานานเกินไปแล้ว!
dasfima

7
ขอขอบคุณ. เจ้านายที่ดีทำไมพวกเขาต้องทำเรื่องเล็กน้อยน่ารำคาญขนาดนี้?
TylerJames

1
ใช้ได้กับไฟล์เนื้อหาเท่านั้น ดูstackoverflow.com/a/25005243/6325722สำหรับวิธีการแบบเต็ม
Johnny Five

อาจทำให้การโทรง่ายขึ้น - queryName (getContentResolver (), uri); ใน MainActivity
Noor Hossain

18

วิธีที่ง่ายที่สุดในการรับชื่อไฟล์:

val fileName = File(uri.path).name
// or
val fileName = uri.pathSegments.last()

หากพวกเขาไม่ได้ให้ชื่อที่ถูกต้องคุณควรใช้:

fun Uri.getName(context: Context): String {
    val returnCursor = context.contentResolver.query(this, null, null, null, null)
    val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
    returnCursor.moveToFirst()
    val fileName = returnCursor.getString(nameIndex)
    returnCursor.close()
    return fileName
}

ใช้File(uri.path).nameงานได้เท่านั้นขอบคุณ!
Sam Chen

17

หากคุณต้องการให้สั้นสิ่งนี้ควรใช้งานได้

Uri uri= data.getData();
File file= new File(uri.getPath());
file.getName();

1
ฉันได้รับชื่อที่มี file.getName () แต่ไม่ใช่ชื่อจริง
Tushar Thakur

1
fileName ของฉันคือ user.jpg แต่ฉันได้รับ "6550" ในการตอบกลับ
Tushar Thakur

1
ไม่ส่งคืนชื่อไฟล์จริง จริงๆแล้วจะส่งคืนส่วนสุดท้ายของ URL ทรัพยากรของคุณ
Emdadul Sawon

สิ่งนี้ใช้ไม่ได้เป็นไฟล์! วันนี้ MediaStore ต้องถอดรหัส URI เป็นส่วนใหญ่ เหตุผลที่ฉันและคนอื่น ๆ ได้รับหมายเลข เนื่องจากเป็น ID ของไฟล์เหล่านั้น
sud007

1
นี่คือคำตอบที่ได้รับเมื่อ 4 ปีที่แล้ว Android มีการเปลี่ยนแปลงทุกรุ่นอย่างเห็นได้ชัด
ซามูเอล

7

ฉันใช้รหัสด้านล่างเพื่อรับชื่อไฟล์และขนาดไฟล์จาก Uri ในโครงการของฉัน

/**
 * Used to get file detail from uri.
 * <p>
 * 1. Used to get file detail (name & size) from uri.
 * 2. Getting file details from uri is different for different uri scheme,
 * 2.a. For "File Uri Scheme" - We will get file from uri & then get its details.
 * 2.b. For "Content Uri Scheme" - We will get the file details by querying content resolver.
 *
 * @param uri Uri.
 * @return file detail.
 */
public static FileDetail getFileDetailFromUri(final Context context, final Uri uri) {
    FileDetail fileDetail = null;
    if (uri != null) {
        fileDetail = new FileDetail();
        // File Scheme.
        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
            File file = new File(uri.getPath());
            fileDetail.fileName = file.getName();
            fileDetail.fileSize = file.length();
        }
        // Content Scheme.
        else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
            Cursor returnCursor =
                    context.getContentResolver().query(uri, null, null, null, null);
            if (returnCursor != null && returnCursor.moveToFirst()) {
                int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
                fileDetail.fileName = returnCursor.getString(nameIndex);
                fileDetail.fileSize = returnCursor.getLong(sizeIndex);
                returnCursor.close();
            }
        }
    }
    return fileDetail;
}

/**
 * File Detail.
 * <p>
 * 1. Model used to hold file details.
 */
public static class FileDetail {

    // fileSize.
    public String fileName;

    // fileSize in bytes.
    public long fileSize;

    /**
     * Constructor.
     */
    public FileDetail() {

    }
}

ช่วยแก้ปัญหาของฉันด้วยการโหลดชื่อไฟล์จากข้อมูลภายนอกหรือภายใน! มีประโยชน์มากขอบคุณ!
Brandon

7

รุ่นที่ย่อที่สุด:

public String getNameFromURI(Uri uri) {
    Cursor c = getContentResolver().query(uri, null, null, null, null);
    c.moveToFirst();
    return c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}

1
อย่าลืมปิดเคอร์เซอร์ :)
BekaBot

5

สำหรับ Kotlin คุณสามารถใช้สิ่งนี้:

object FileUtils {

   fun Context.getFileName(uri: Uri): String?
        = when (uri.scheme) {
            ContentResolver.SCHEME_FILE -> File(uri.path).name
            ContentResolver.SCHEME_CONTENT -> getCursorContent(uri)
            else -> null
        }

    private fun Context.getCursorContent(uri: Uri): String? 
        = try {
            contentResolver.query(uri, null, null, null, null)?.let { cursor ->
                cursor.run {
                    if (moveToFirst()) getString(getColumnIndex(OpenableColumns.DISPLAY_NAME))
                    else null
                }.also { cursor.close() }
            }
        } catch (e : Exception) { null }

คำตอบที่ดี แต่ในความคิดของฉันควรแทรกความสนุกเหล่านี้ (Context.getFileName และ Context.getCursorContent) ในไฟล์ที่มีชื่อ 'บริบท' ลบคำวัตถุ FileUtils และใช้เป็นส่วนขยายตัวอย่างเช่น: val txtFileName = context.getFileName (uri)
Alexey Simchenko

@LumisD คุณสามารถนำเข้าส่วนขยายเหล่านี้ในไฟล์ใดก็ได้คำแนะนำของคุณถูกต้อง แต่ฉันเกลียดเมื่อวิธีการเป็นสากล ฉันต้องการดูวิธีการบางอย่างก็ต่อเมื่อฉันนำเข้าและไม่เสมอไป และบางครั้งฉันชอบมีชื่อวิธีการเดียวกันและแหล่งที่มาที่แตกต่างกันดังนั้นฉันจึงนำเข้าสิ่งที่ฉันต้องการในตำแหน่งที่ถูกต้อง :)
Tamim Attafi

คุณสามารถนำเข้าด้วยวิธีนี้: นำเข้า com.example.FileUtils.getFileName หรือเพียงแค่เขียน context.getFileName (uri) แล้วกด Alt + Enter จากนั้น IDE ของคุณจะดำเนินการให้ :)
Tamim Attafi

4
public String getFilename() 
{
/*  Intent intent = getIntent();
    String name = intent.getData().getLastPathSegment();
    return name;*/
    Uri uri=getIntent().getData();
    String fileName = null;
    Context context=getApplicationContext();
    String scheme = uri.getScheme();
    if (scheme.equals("file")) {
        fileName = uri.getLastPathSegment();
    }
    else if (scheme.equals("content")) {
        String[] proj = { MediaStore.Video.Media.TITLE };
        Uri contentUri = null;
        Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
        if (cursor != null && cursor.getCount() != 0) {
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE);
            cursor.moveToFirst();
            fileName = cursor.getString(columnIndex);
        }
    }
    return fileName;
}

สิ่งนี้ไม่ได้ผลในกรณีของฉัน แต่ Vasanth ตอบได้
Nabzi

4

หากคุณต้องการมีชื่อไฟล์ที่มีนามสกุลฉันใช้ฟังก์ชันนี้เพื่อรับมัน นอกจากนี้ยังทำงานร่วมกับการเลือกไฟล์ของ Google ไดรฟ์

public static String getFileName(Uri uri) {
    String result;

    //if uri is content
    if (uri.getScheme() != null && uri.getScheme().equals("content")) {
        Cursor cursor = global.getInstance().context.getContentResolver().query(uri, null, null, null, null);
        try {
            if (cursor != null && cursor.moveToFirst()) {
                //local filesystem
                int index = cursor.getColumnIndex("_data");
                if(index == -1)
                    //google drive
                    index = cursor.getColumnIndex("_display_name");
                result = cursor.getString(index);
                if(result != null)
                    uri = Uri.parse(result);
                else
                    return null;
            }
        } finally {
            cursor.close();
        }
    }

    result = uri.getPath();

    //get filename + ext of path
    int cut = result.lastIndexOf('/');
    if (cut != -1)
        result = result.substring(cut + 1);
    return result;
}

1
ขอบคุณสำหรับคำตอบสิ่งนี้ช่วยฉันได้
Sakhawat Hossain

2
String Fpath = getPath(this, uri) ;
File file = new File(Fpath);
String filename = file.getName();

4
คุณช่วยอธิบายหน่อยได้ไหมว่าโค้ดของคุณใช้ทำอะไร วิธีนี้คำตอบของคุณจะมีประโยชน์มากขึ้นสำหรับผู้ใช้รายอื่นที่สะดุดกับปัญหานี้ ขอบคุณ
wmk

ด้วยเหตุผลบางประการสิ่งนี้ใช้ไม่ได้กับ marshmellow มันแค่ส่งออก "เสียงและตัวเลขบางส่วน"
Alex

1

คำตอบในเวอร์ชันของฉันคล้ายกับ @Stefan Haustein มาก ผมพบคำตอบบน Android หน้านักพัฒนาซอฟต์แวร์ข้อมูลการเรียกไฟล์ ; ข้อมูลที่นี่มีการย่อในหัวข้อเฉพาะนี้มากกว่าในไซต์คู่มือStorage Access Framework OpenableColumns.DISPLAY_NAMEผลจากการค้นหาชื่อแฟ้มดัชนีคอลัมน์ที่มีคือ ไม่มีคำตอบ / วิธีแก้ไขอื่น ๆ สำหรับดัชนีคอลัมน์ที่ใช้ได้ผลสำหรับฉัน ด้านล่างนี้คือฟังก์ชั่นตัวอย่าง:

 /**
 * @param uri uri of file.
 * @param contentResolver access to server app.
 * @return the name of the file.
 */
def extractFileName(uri: Uri, contentResolver: ContentResolver): Option[String] = {

    var fileName: Option[String] = None
    if (uri.getScheme.equals("file")) {

        fileName = Option(uri.getLastPathSegment)
    } else if (uri.getScheme.equals("content")) {

        var cursor: Cursor = null
        try {

            // Query the server app to get the file's display name and size.
            cursor = contentResolver.query(uri, null, null, null, null)

            // Get the column indexes of the data in the Cursor,
            // move to the first row in the Cursor, get the data.
            if (cursor != null && cursor.moveToFirst()) {

                val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                fileName = Option(cursor.getString(nameIndex))
            }

        } finally {

            if (cursor != null) {
                cursor.close()
            }

        }

    }

    fileName
}

1

ขั้นแรกคุณต้องแปลงURIวัตถุของคุณเป็นURLวัตถุจากนั้นใช้Fileวัตถุเพื่อดึงชื่อไฟล์:

try
    {
        URL videoUrl = uri.toURL();
        File tempFile = new File(videoUrl.getFile());
        String fileName = tempFile.getName();
    }
    catch (Exception e)
    {

    }

แค่นั้นแหละง่ายมาก


1

Stefan Haustein ฟังก์ชั่นสำหรับ xamarin / c #:

public string GetFilenameFromURI(Android.Net.Uri uri)
        {
            string result = null;
            if (uri.Scheme == "content")
            {
                using (var cursor = Application.Context.ContentResolver.Query(uri, null, null, null, null))
                {
                    try
                    {
                        if (cursor != null && cursor.MoveToFirst())
                        {
                            result = cursor.GetString(cursor.GetColumnIndex(OpenableColumns.DisplayName));
                        }
                    }
                    finally
                    {
                        cursor.Close();
                    }
                }
            }
            if (result == null)
            {
                result = uri.Path;
                int cut = result.LastIndexOf('/');
                if (cut != -1)
                {
                    result = result.Substring(cut + 1);
                }
            }
            return result;
        }

1

สิ่งนี้ใช้งานได้จริงสำหรับฉัน:

private String uri2filename() {

    String ret;
    String scheme = uri.getScheme();

    if (scheme.equals("file")) {
        ret = uri.getLastPathSegment();
    }
    else if (scheme.equals("content")) {
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            ret = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
        }
   }
   return ret;
}

0

โปรดลองสิ่งนี้:

  private String displayName(Uri uri) {

             Cursor mCursor =
                     getApplicationContext().getContentResolver().query(uri, null, null, null, null);
             int indexedname = mCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
             mCursor.moveToFirst();
             String filename = mCursor.getString(indexedname);
             mCursor.close();
             return filename;
 }

0

การรวมกันของคำตอบทั้งหมด

นี่คือสิ่งที่ฉันได้มาหลังจากอ่านคำตอบทั้งหมดที่นำเสนอที่นี่รวมถึงสิ่งที่ Airgram ทำใน SDK ของพวกเขา - ยูทิลิตี้ที่ฉันได้เปิดที่มาบน Github:

https://github.com/mankum93/UriUtilsAndroid/tree/master/app/src/main/java/com/androiduriutils

การใช้งาน

ง่ายเหมือนการโทร UriUtils.getDisplayNameSize() . มีทั้งชื่อและขนาดของเนื้อหา

บันทึก:ใช้ได้เฉพาะกับเนื้อหา: // Uri

นี่คือข้อมูลคร่าวๆเกี่ยวกับรหัส:

/**
 * References:
 * - https://www.programcreek.com/java-api-examples/?code=MLNO/airgram/airgram-master/TMessagesProj/src/main/java/ir/hamzad/telegram/MediaController.java
 * - /programming/5568874/how-to-extract-the-file-name-from-uri-returned-from-intent-action-get-content
 *
 * @author Manish@bit.ly/2HjxA0C
 * Created on: 03-07-2020
 */
public final class UriUtils {


    public static final int CONTENT_SIZE_INVALID = -1;

    /**
     * @param context context
     * @param contentUri content Uri, i.e, of the scheme <code>content://</code>
     * @return The Display name and size for content. In case of non-determination, display name
     * would be null and content size would be {@link #CONTENT_SIZE_INVALID}
     */
    @NonNull
    public static DisplayNameAndSize getDisplayNameSize(@NonNull Context context, @NonNull Uri contentUri){

        final String scheme = contentUri.getScheme();
        if(scheme == null || !scheme.equals(ContentResolver.SCHEME_CONTENT)){
            throw new RuntimeException("Only scheme content:// is accepted");
        }

        final DisplayNameAndSize displayNameAndSize = new DisplayNameAndSize();
        displayNameAndSize.size = CONTENT_SIZE_INVALID;

        String[] projection = new String[]{MediaStore.Images.Media.DATA, OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE};
        Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
        try {
            if (cursor != null && cursor.moveToFirst()) {

                // Try extracting content size

                int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
                if (sizeIndex != -1) {
                    displayNameAndSize.size = cursor.getLong(sizeIndex);
                }

                // Try extracting display name
                String name = null;

                // Strategy: The column name is NOT guaranteed to be indexed by DISPLAY_NAME
                // so, we try two methods
                int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                if (nameIndex != -1) {
                    name = cursor.getString(nameIndex);
                }

                if (nameIndex == -1 || name == null) {
                    nameIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
                    if (nameIndex != -1) {
                        name = cursor.getString(nameIndex);
                    }
                }
                displayNameAndSize.displayName = name;
            }
        }
        finally {
            if(cursor != null){
                cursor.close();
            }
        }

        // We tried querying the ContentResolver...didn't work out
        // Try extracting the last path segment
        if(displayNameAndSize.displayName == null){
            displayNameAndSize.displayName = contentUri.getLastPathSegment();
        }

        return displayNameAndSize;
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.