UWP - 将 MediaFile 转换为 StorageFile
UWP - Converting MediaFile to StorageFile
我需要将类型Plugin.Media.Abstractions.MediaFile
转换为Windows.Storage.StorageFile
。
原因是我得到一个 MediaFile
,我想通过路径上传到服务器,但在 UWP 中你必须使用 StorageFiles 而不是文件路径,否则 UWP 不知道用户拥有该文件的权限,只是拒绝访问。所以我想将 MediaFile 转换为 StorageFile 以便能够在用户的临时文件夹中创建文件的副本。此文件夹中的文件可以通过文件路径访问。
这就是我试过的方法:
Stream stream = _mediaFile.GetStream();
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
string streamText = reader.ReadToEnd();
_websocketManager.sendFileMessage(_selectedChat.chatId, _nachrichttext, streamText);
sendFileMessage()
是接口中的一种方法,因此参数必须是字符串,我无法更改它。最初这个字符串应该是路径,所以这是我的一个便宜的解决方法,但对于我想要实现的目标来说这是合法的。
在WebsocketManager中,这是我的方法sendFileMessage()
:
byte[] byteArray = Encoding.UTF8.GetBytes(streamText);
MemoryStream stream = new MemoryStream(byteArray);
StorageFolder temporaryFolder = ApplicationData.Current.TemporaryFolder;
var temporaryFile = await temporaryFolder.CreateFileAsync("temporaryFile", CreationCollisionOption.ReplaceExisting);
using (var fileStream = File.Create(temporaryFolder.Path + "\TemporaryFile")) // TODO: How to data type? (.png, .jpg, ...)
{
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fileStream);
}
string filePath = temporaryFile.Path;
string remoteFilePath = null;
if (!string.IsNullOrEmpty(filePath))
{
await StorageFile.GetFileFromPathAsync(filePath);
remoteFilePath = await uploadFile(filePath);
}
dataWriter.WriteString(WebsocketRequestFactory.Create(SocketEventsEnm.MESSAGE_OUT, chatId, message, remoteFilePath, TypeEnm.IMAGE));
await SendData(dataWriter);
await temporaryFile.DeleteAsync();
此外,正如我在代码中评论的那样,我需要找出 MediaFile
是哪种数据类型(.png、.jpg 等)。
可以参考xamarin官方文档Working with Files,读写文件,需要使用各个平台原生的文件API
对于 UWP 应用程序,您可以像这样在可移植项目中创建接口ISaveAndLoad
:
public interface ISaveAndLoad
{
void SaveImage(string filename, Stream filestream);
Task<string> LoadImage(string filename);
}
然后在您的 UWP 应用中创建一个 class 继承并实现此 ISaveAndLoad
接口,如下所示:
public class SaveAndLoad_UWP : ISaveAndLoad
{
public async Task<string> LoadImage(string filename)
{
StorageFolder local = ApplicationData.Current.LocalFolder;
StorageFile file = await local.GetFileAsync(filename);
return file.Path;
}
public async void SaveImage(string filename, Stream filestream)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile File = await localFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
using (var stream = await File.OpenStreamForWriteAsync())
{
await filestream.CopyToAsync(stream);
}
}
}
最后,当你选择一个图像时,你可以将 MediaFile
转换为 StorageFile
并得到临时文件的路径,如下所示:
var file = await CrossMedia.Current.PickPhotoAsync(); //pick a file
if (file == null)
return;
var path = file.Path;
var filetype = path.Split('.').Last(); //get file type
var filestream = file.GetStream();
DependencyService.Get<ISaveAndLoad>().SaveImage("temp." + filetype, filestream); //save file
var temppath = DependencyService.Get<ISaveAndLoad>().LoadImage("temp." + filetype); //get temp file's path
我需要将类型Plugin.Media.Abstractions.MediaFile
转换为Windows.Storage.StorageFile
。
原因是我得到一个 MediaFile
,我想通过路径上传到服务器,但在 UWP 中你必须使用 StorageFiles 而不是文件路径,否则 UWP 不知道用户拥有该文件的权限,只是拒绝访问。所以我想将 MediaFile 转换为 StorageFile 以便能够在用户的临时文件夹中创建文件的副本。此文件夹中的文件可以通过文件路径访问。
这就是我试过的方法:
Stream stream = _mediaFile.GetStream();
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
string streamText = reader.ReadToEnd();
_websocketManager.sendFileMessage(_selectedChat.chatId, _nachrichttext, streamText);
sendFileMessage()
是接口中的一种方法,因此参数必须是字符串,我无法更改它。最初这个字符串应该是路径,所以这是我的一个便宜的解决方法,但对于我想要实现的目标来说这是合法的。
在WebsocketManager中,这是我的方法sendFileMessage()
:
byte[] byteArray = Encoding.UTF8.GetBytes(streamText);
MemoryStream stream = new MemoryStream(byteArray);
StorageFolder temporaryFolder = ApplicationData.Current.TemporaryFolder;
var temporaryFile = await temporaryFolder.CreateFileAsync("temporaryFile", CreationCollisionOption.ReplaceExisting);
using (var fileStream = File.Create(temporaryFolder.Path + "\TemporaryFile")) // TODO: How to data type? (.png, .jpg, ...)
{
stream.Seek(0, SeekOrigin.Begin);
stream.CopyTo(fileStream);
}
string filePath = temporaryFile.Path;
string remoteFilePath = null;
if (!string.IsNullOrEmpty(filePath))
{
await StorageFile.GetFileFromPathAsync(filePath);
remoteFilePath = await uploadFile(filePath);
}
dataWriter.WriteString(WebsocketRequestFactory.Create(SocketEventsEnm.MESSAGE_OUT, chatId, message, remoteFilePath, TypeEnm.IMAGE));
await SendData(dataWriter);
await temporaryFile.DeleteAsync();
此外,正如我在代码中评论的那样,我需要找出 MediaFile
是哪种数据类型(.png、.jpg 等)。
可以参考xamarin官方文档Working with Files,读写文件,需要使用各个平台原生的文件API
对于 UWP 应用程序,您可以像这样在可移植项目中创建接口ISaveAndLoad
:
public interface ISaveAndLoad
{
void SaveImage(string filename, Stream filestream);
Task<string> LoadImage(string filename);
}
然后在您的 UWP 应用中创建一个 class 继承并实现此 ISaveAndLoad
接口,如下所示:
public class SaveAndLoad_UWP : ISaveAndLoad
{
public async Task<string> LoadImage(string filename)
{
StorageFolder local = ApplicationData.Current.LocalFolder;
StorageFile file = await local.GetFileAsync(filename);
return file.Path;
}
public async void SaveImage(string filename, Stream filestream)
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile File = await localFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
using (var stream = await File.OpenStreamForWriteAsync())
{
await filestream.CopyToAsync(stream);
}
}
}
最后,当你选择一个图像时,你可以将 MediaFile
转换为 StorageFile
并得到临时文件的路径,如下所示:
var file = await CrossMedia.Current.PickPhotoAsync(); //pick a file
if (file == null)
return;
var path = file.Path;
var filetype = path.Split('.').Last(); //get file type
var filestream = file.GetStream();
DependencyService.Get<ISaveAndLoad>().SaveImage("temp." + filetype, filestream); //save file
var temppath = DependencyService.Get<ISaveAndLoad>().LoadImage("temp." + filetype); //get temp file's path