Android:从现有URI保存文件

时间:2012-10-30 06:09:41

标签: android android-intent media

如何从现有URI中保存媒体文件(例如.mp3),我从隐含意图中获取该文件?

9 个答案:

答案 0 :(得分:25)

使用此方法,它可以正常工作

void savefile(URI sourceuri)
{
    String sourceFilename= sourceuri.getPath();
    String destinationFilename = android.os.Environment.getExternalStorageDirectory().getPath()+File.separatorChar+"abc.mp3";

    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;

    try {
      bis = new BufferedInputStream(new FileInputStream(sourceFilename));
      bos = new BufferedOutputStream(new FileOutputStream(destinationFilename, false));
      byte[] buf = new byte[1024];
      bis.read(buf);
      do {
        bos.write(buf);
      } while(bis.read(buf) != -1);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (bis != null) bis.close();
        if (bos != null) bos.close();
      } catch (IOException e) {
            e.printStackTrace();
      }
    }
}

答案 1 :(得分:8)

private static String FILE_NAM  = "video";
String outputfile = getFilesDir() + File.separator+FILE_NAM+"_tmp.mp4";

InputStream in = getContentResolver().openInputStream(videoFileUri);
private static File createFileFromInputStream(InputStream inputStream, String fileName) {

   try{
      File f = new File(fileName);
      f.setWritable(true, false);
      OutputStream outputStream = new FileOutputStream(f);
      byte buffer[] = new byte[1024];
      int length = 0;

      while((length=inputStream.read(buffer)) > 0) {
        outputStream.write(buffer,0,length);
      }

      outputStream.close();
      inputStream.close();

      return f;
   }catch (IOException e) {
       System.out.println("error in creating a file");
       e.printStackTrace();
   }

return null;

   }

答案 2 :(得分:6)

如果从Google云端硬盘收到Uri,它也可以是虚拟文件Uri。来自CommonsWare的Check this文章了解更多信息。所以你在从Uri保存文件时也必须考虑这个条件。

要查找文件Uri是否为虚拟,您可以使用

private static boolean isVirtualFile(Context context, Uri uri) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        if (!DocumentsContract.isDocumentUri(context, uri)) {
            return false;
        }
        Cursor cursor = context.getContentResolver().query(
                uri,
                new String[]{DocumentsContract.Document.COLUMN_FLAGS},
                null, null, null);
        int flags = 0;
        if (cursor.moveToFirst()) {
            flags = cursor.getInt(0);
        }
        cursor.close();
        return (flags & DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT) != 0;
    } else {
        return false;
    }
}

您可以从此虚拟文件中获取流数据,如下所示:

private static InputStream getInputStreamForVirtualFile(Context context, Uri uri, String mimeTypeFilter)
        throws IOException {

    ContentResolver resolver = context.getContentResolver();
    String[] openableMimeTypes = resolver.getStreamTypes(uri, mimeTypeFilter);
    if (openableMimeTypes == null || openableMimeTypes.length < 1) {
        throw new FileNotFoundException();
    }
    return resolver
            .openTypedAssetFileDescriptor(uri, openableMimeTypes[0], null)
            .createInputStream();
}

要查找MIME类型,请尝试

private static String getMimeType(String url) {
    String type = null;
    String extension = MimeTypeMap.getFileExtensionFromUrl(url);
    if (extension != null) {
        type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    }
    return type;
}

总的来说,你可以使用

public static boolean saveFile(Context context, String name, Uri sourceuri, String destinationDir, String destFileName) {

    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    InputStream input = null;
    boolean hasError = false;

    try {
        if (isVirtualFile(context, sourceuri)) {
            input = getInputStreamForVirtualFile(context, sourceuri, getMimeType(name));
        } else {
            input = context.getContentResolver().openInputStream(sourceuri);
        }

        boolean directorySetupResult;
        File destDir = new File(destinationDir);
        if (!destDir.exists()) {
            directorySetupResult = destDir.mkdirs();
        } else if (!destDir.isDirectory()) {
            directorySetupResult = replaceFileWithDir(destinationDir);
        } else {
            directorySetupResult = true;
        }

        if (!directorySetupResult) {
            hasError = true;
        } else {
            String destination = destinationDir + File.separator + destFileName;
            int originalsize = input.available();

            bis = new BufferedInputStream(input);
            bos = new BufferedOutputStream(new FileOutputStream(destination));
            byte[] buf = new byte[originalsize];
            bis.read(buf);
            do {
                bos.write(buf);
            } while (bis.read(buf) != -1);
        }
    } catch (Exception e) {
        e.printStackTrace();
        hasError = true;
    } finally {
        try {
            if (bos != null) {
                bos.flush();
                bos.close();
            }
        } catch (Exception ignored) {
        }
    }

    return !hasError;
}

private static boolean replaceFileWithDir(String path) {
    File file = new File(path);
    if (!file.exists()) {
        if (file.mkdirs()) {
            return true;
        }
    } else if (file.delete()) {
        File folder = new File(path);
        if (folder.mkdirs()) {
            return true;
        }
    }
    return false;
}

从AsycTask调用此方法。如果这有帮助,请告诉我。

答案 3 :(得分:2)

1.从URI路径创建文件:

File from = new File(uri.toString());

2.创建另一个文件,将文件保存为:

File to = new File("target file path");

3.将文件重命名为:

from.renameTo(to);

使用此功能,默认路径中的文件将自动删除并在新路径中创建。

答案 4 :(得分:1)

这是最简单,最干净的:

private void saveFile(Uri sourceUri, File destination)
    try {
        File source = new File(sourceUri.getPath());
        FileChannel src = new FileInputStream(source).getChannel();
        FileChannel dst = new FileOutputStream(destination).getChannel();
        dst.transferFrom(src, 0, src.size());
        src.close();
        dst.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

答案 5 :(得分:0)

供将来的访客使用。 Kotlin 代码可复制从选择器意图中选择的文件。

val file = File("//add your destination address")
                    val fileContentURI = FileProvider.getUriForFile(context!!, "com.minutecodes.openote.fileprovider", file)
                    val out = context!!.contentResolver.openOutputStream(fileContentURI)
                    context!!.contentResolver.openInputStream(clip.getItemAt(0)!!.uri)!!.copyTo(out!!, DEFAULT_BUFFER_SIZE)

答案 6 :(得分:0)

从外部来源收到<FlatList onScrollBeginDrag={() => console.log('begin')} onScrollEndDrag={() => console.log('end')} data={[{key: 'a'}, {key: 'b'}]} renderItem={({ item }) => ( <View style={{ backgroundColor: 'transparent' }}> <Text>{item.key}</Text> </View> )} /> 时,保存文件的最佳方法是从流中:

android.net.Uri

try (InputStream ins = activity.getContentResolver().openInputStream(source_uri)) { File dest = new File(destination_path); createFileFromStream(ins, dest); } catch (Exception ex) { Log.e("Save File", ex.getMessage()); ex.printStackTrace(); } 方法:

createFileFromStream

答案 7 :(得分:0)

您可以使用

new File(uri.getPath());

答案 8 :(得分:0)

我已使用以下代码将文件从现有的Uri中保存,并从Intent中发还给我的应用托管的Uri:

 private void copyFile(Uri pathFrom, Uri pathTo) throws IOException {
        try (InputStream in = getContentResolver().openInputStream(pathFrom)) {
            if(in == null) return;
            try (OutputStream out = getContentResolver().openOutputStream(pathTo)) {
                if(out == null) return;
                // Transfer bytes from in to out
                byte[] buf = new byte[1024];
                int len;
                while ((len = in.read(buf)) > 0) {
                    out.write(buf, 0, len);
                }
            }
        }
    }