如何使用存储访问框架中的 getContentResolver().openFileDescriptor() 将文件从 Dropbox/Drive/Onedrive 复制到特定路径?
How can I copy a file from Dropbox/Drive/Onedrive to a specific path using getContentResolver().openFileDescriptor() from Storage Access Framework?
我正在尝试将文件从通用托管文件服务复制为 Dropbox/Drive/Onedrive 到我设备中的特定路径。
我创建了一个复制 jpg 文件的工作示例,但我想创建的是用于复制这些类型的版本:.docx、.pdf、.pptx、.jpg、.jpeg、.png、. gif、.mp3、.mp4、.xlsx.
我需要做什么?如何修改我的代码?
谢谢
// the flow start from here
public void newFile() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select file"), NEW_FILE_PRIVATE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == NEW_FILE_PRIVATE && resultCode == Activity.RESULT_OK) {
if (data != null) {
Uri currentUri = null;
currentUri = data.getData();
String contentString = currentUri.toString();
if (contentString.contains("com.dropbox.android") ||
contentString.contains("com.microsoft.skydrive") ||
contentString.contains("com.google.android.apps.docs.storage")) {
try {
copyFileContent(currentUri);
} catch (IOException e) {
Log.e("cloud error", "error");
}
}
}
}
}
private String copyFileContent(Uri uri) throws IOException {
ParcelFileDescriptor pFileDescriptor = getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = pFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
pFileDescriptor.close();
/* temporary path */
String extension = getMimeType(getApplicationContext(), uri);
String temporaryFilePath = Environment.getExternalStorageDirectory().toString()
.concat("/").concat("temporaryfile")
.concat(".").concat(extension);
File file = new File(temporaryFilePath);
OutputStream outStream = null;
try {
/* make a new bitmap from your file */
outStream = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return temporaryFilePath;
}
编辑
感谢@CommonsWare,我编写了一个使用以下代码获取文件扩展名的解决方案:
public String getExtension(Context context, Uri uri) {
String extension;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
final MimeTypeMap mime = MimeTypeMap.getSingleton();
extension = mime.getExtensionFromMimeType(context.getContentResolver().getType(uri));
} else {
extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
}
return extension;
}
编辑 2
在@Greenapps 的帮助下,我实现了这个解决方案:
private String copyFileContent(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
/* temporary path */
String extension = getMimeType(getApplicationContext(), uri);
String temporaryFilePath = Environment.getExternalStorageDirectory().toString()
.concat("/").concat("temporaryfile")
.concat(".").concat(extension);
OutputStream outStream = new FileOutputStream(temporaryFilePath);
final byte[] b = new byte[8192];
for (int r;(r = inputStream.read(b)) != -1;) outStream.write(b, 0, r);
return temporaryFilePath;
}
是否存在获取文件名而不是命名文件的方法"temporary file"?
编辑 3
private String copyFileContent(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
String uriString = uri.toString();
String fileName = "";
if (!uriString.contains("com.dropbox.android")) {
Cursor returnCursor = getContentResolver().query(uri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
fileName = returnCursor.getString(nameIndex);
} else {
fileName = uriString.substring(uriString.lastIndexOf("/") + 1, uriString.lastIndexOf("."));
}
/* temporary path */
String extension = getMimeType(getApplicationContext(), uri);
String temporaryFilePath = Environment.getExternalStorageDirectory().toString()
.concat("/").concat(egoName)
.concat("/").concat("PRIVATE")
.concat("/").concat(fileName)
.concat(".").concat(extension);
OutputStream outStream = new FileOutputStream(temporaryFilePath);
final byte[] b = new byte[8192];
for (int r;
(r = inputStream.read(b)) != -1;) outStream.write(b, 0, r);
return temporaryFilePath;
}
How can I get file name and extension from Storage Access Framework using getContentResolver().openFileDescriptor()?
没有文件名或扩展名。您正在处理内容,而不是文件。您可以获得 "display name"(例如 DocumentFile
和 getName()
),但这不必是文件名或包含任何类型的文件扩展名。
This code works if my file is a jpg, but what I'm trying to do is to find a solution for every type of file without using the intent.setType("image/*") or generalizing it
通过DocumentFile
和getType()
获取内容的MIME类型。使用 MimeTypeMap
帮助您将其转换为候选文件扩展名。
大约一天后,很明显您只想复制文件。
通过打开 InputStream
.
以正常方式进行
InputStream is = getContentResolver().openInputStream(uri);
然后从流中读取块并将它们写入FileOutputStream
。
由于 DropBox 中充满了文件,因此可以在 data.getData().getPath()
中找到文件名(带扩展名)。但是使用显示名称列是一个更好的主意。
我正在尝试将文件从通用托管文件服务复制为 Dropbox/Drive/Onedrive 到我设备中的特定路径。
我创建了一个复制 jpg 文件的工作示例,但我想创建的是用于复制这些类型的版本:.docx、.pdf、.pptx、.jpg、.jpeg、.png、. gif、.mp3、.mp4、.xlsx.
我需要做什么?如何修改我的代码?
谢谢
// the flow start from here
public void newFile() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select file"), NEW_FILE_PRIVATE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == NEW_FILE_PRIVATE && resultCode == Activity.RESULT_OK) {
if (data != null) {
Uri currentUri = null;
currentUri = data.getData();
String contentString = currentUri.toString();
if (contentString.contains("com.dropbox.android") ||
contentString.contains("com.microsoft.skydrive") ||
contentString.contains("com.google.android.apps.docs.storage")) {
try {
copyFileContent(currentUri);
} catch (IOException e) {
Log.e("cloud error", "error");
}
}
}
}
}
private String copyFileContent(Uri uri) throws IOException {
ParcelFileDescriptor pFileDescriptor = getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = pFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
pFileDescriptor.close();
/* temporary path */
String extension = getMimeType(getApplicationContext(), uri);
String temporaryFilePath = Environment.getExternalStorageDirectory().toString()
.concat("/").concat("temporaryfile")
.concat(".").concat(extension);
File file = new File(temporaryFilePath);
OutputStream outStream = null;
try {
/* make a new bitmap from your file */
outStream = new FileOutputStream(file);
image.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return temporaryFilePath;
}
编辑 感谢@CommonsWare,我编写了一个使用以下代码获取文件扩展名的解决方案:
public String getExtension(Context context, Uri uri) {
String extension;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
final MimeTypeMap mime = MimeTypeMap.getSingleton();
extension = mime.getExtensionFromMimeType(context.getContentResolver().getType(uri));
} else {
extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
}
return extension;
}
编辑 2 在@Greenapps 的帮助下,我实现了这个解决方案:
private String copyFileContent(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
/* temporary path */
String extension = getMimeType(getApplicationContext(), uri);
String temporaryFilePath = Environment.getExternalStorageDirectory().toString()
.concat("/").concat("temporaryfile")
.concat(".").concat(extension);
OutputStream outStream = new FileOutputStream(temporaryFilePath);
final byte[] b = new byte[8192];
for (int r;(r = inputStream.read(b)) != -1;) outStream.write(b, 0, r);
return temporaryFilePath;
}
是否存在获取文件名而不是命名文件的方法"temporary file"?
编辑 3
private String copyFileContent(Uri uri) throws IOException {
InputStream inputStream = getContentResolver().openInputStream(uri);
String uriString = uri.toString();
String fileName = "";
if (!uriString.contains("com.dropbox.android")) {
Cursor returnCursor = getContentResolver().query(uri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
returnCursor.moveToFirst();
fileName = returnCursor.getString(nameIndex);
} else {
fileName = uriString.substring(uriString.lastIndexOf("/") + 1, uriString.lastIndexOf("."));
}
/* temporary path */
String extension = getMimeType(getApplicationContext(), uri);
String temporaryFilePath = Environment.getExternalStorageDirectory().toString()
.concat("/").concat(egoName)
.concat("/").concat("PRIVATE")
.concat("/").concat(fileName)
.concat(".").concat(extension);
OutputStream outStream = new FileOutputStream(temporaryFilePath);
final byte[] b = new byte[8192];
for (int r;
(r = inputStream.read(b)) != -1;) outStream.write(b, 0, r);
return temporaryFilePath;
}
How can I get file name and extension from Storage Access Framework using getContentResolver().openFileDescriptor()?
没有文件名或扩展名。您正在处理内容,而不是文件。您可以获得 "display name"(例如 DocumentFile
和 getName()
),但这不必是文件名或包含任何类型的文件扩展名。
This code works if my file is a jpg, but what I'm trying to do is to find a solution for every type of file without using the intent.setType("image/*") or generalizing it
通过DocumentFile
和getType()
获取内容的MIME类型。使用 MimeTypeMap
帮助您将其转换为候选文件扩展名。
大约一天后,很明显您只想复制文件。
通过打开 InputStream
.
InputStream is = getContentResolver().openInputStream(uri);
然后从流中读取块并将它们写入FileOutputStream
。
由于 DropBox 中充满了文件,因此可以在 data.getData().getPath()
中找到文件名(带扩展名)。但是使用显示名称列是一个更好的主意。