当您将内容 Uri 取回时,您对该 UriOnActivityResult
具有临时权限(并因此具有写入权限),因此您可以在写入模式下打开基于宗地的文件描述符,从该宗地的文件描述符创建输出流并写入任何内容你需要它。
将资产流写入用户选择的文件的示例:
protected async override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
if (resultCode == Result.Ok && requestCode == 43)
{
var buffer = new byte[1024];
using (var pFD = ContentResolver.OpenFileDescriptor(data.Data, "w"))
using (var outputSteam = new FileOutputStream(pFD.FileDescriptor))
using (var inputStream = Assets.Open("somePicture.png"))
{
while (inputStream.CanRead && inputStream.IsDataAvailable())
{
var readCount = await inputStream.ReadAsync(buffer, 0, buffer.Length);
await outputSteam.WriteAsync(buffer, 0, readCount);
}
}
}
base.OnActivityResult(requestCode, resultCode, data);
}
更新(性能):
仅供参考,如果您要保存/流式传输大文件,请避免在流上使用异步版本的读取和写入,而只需启动一个线程(或通过 Task.Run 使用线程池中的一个)。
注意:由于所有异步/等待开销,这总是会更快,并且有点像我通常会这样做(通常根据文件大小快 2 倍(+))。
if (resultCode == Result.Ok && requestCode == 43)
{
await Task.Run(() =>
{
// Buffer size can be "tuned" to enhance read/write performance
var buffer = new byte[1024];
using (var pFD = ContentResolver.OpenFileDescriptor(data.Data, "w"))
using (var outputSteam = new FileOutputStream(pFD.FileDescriptor))
using (var inputStream = Assets.Open("her.png"))
{
while (inputStream.CanRead && inputStream.IsDataAvailable())
{
var readCount = inputStream.Read(buffer, 0, buffer.Length);
outputSteam.Write(buffer, 0, readCount);
}
}
});
}