C# - 多次处理Stream时遇到问题

时间:2016-02-18 10:22:00

标签: c# wcf stream

我有一个Android移动应用程序,具有设置个人资料图片的功能。

我将包含图像路径的变量发送到执行以下操作的方法:

string imagePath = _ProfilePicture.GetTag (Resource.String.profile_picture_path).ToString ();
byte[] imageBytes = System.IO.File.ReadAllBytes(imagePath);
Stream imageStream = new MemoryStream(imageBytes);

在这段代码之后,我将imageStream变量发送到位于WCF服务上的UploadUserProfilePicture(imageStream);

目前它只发送流,但因为我们无法发送包含扩展名的其他参数。我们将所有图像保存为png。然而,我找到了一个库,需要将流解析为字节,然后根据文件类型可以检索的字节。

然而,当我尝试使用相同的流将文件写入服务器上的位置时,位置位于末尾,因此创建的文件始终为0字节。

我试过了: 在另一个方法中转换为Bytes并仅返回fileType,但原始位置仍然在结尾。 CopyTo函数给了我相同的结果。 我尝试使用Seek函数并将其位置设置为零,但是我得到了NotSupportedException。

我也尝试了这个:

string content;
var reader = new StreamReader(image);
content = reader.ReadToEnd();

image.Dispose();
image = new MemoryStream(Encoding.UTF8.GetBytes(content));

^这似乎会破坏流,因为我无法获取FileType,也无法将其写入上述位置。

我还看过:How to read a Stream and reset its position to zero even if stream.CanSeek == false

这是WCF服务上的方法:

public Result UploadUserProfilePicture(Stream image)
    {
        try
        {
            FileType fileType = CommonMethods.ReadToEnd(image).GetFileType();

            Guid guid = Guid.NewGuid();
            string imageName = guid.ToString() + "." + fileType.Extension;
            var buf = new byte[1024];
            var path = Path.Combine(@"C:\" + imageName);
            int len = 0;
            using (var fs = File.Create(path))
            {
                while ((len = image.Read(buf, 0, buf.Length)) > 0)
                {
                    fs.Write(buf, 0, len);
                }
            }

            return new Result
            {
                Success = true,
                Message = imageName
            };
        }
        catch(Exception ex)
        {
            return new Result
            {
                Success = false,
                Message = ex.ToString()
            };
        }

使用的图书馆链接:https://github.com/Muraad/Mime-Detective CommonMethods.ReadToEnd(image)方法可以在这里找到:How to convert an Stream into a byte[] in C#?作为问题的答案

我希望这是关于我的问题的足够信息。

1 个答案:

答案 0 :(得分:1)

在服务器端,您收到来自WCF的不支持搜索操作的流。但是,您可以将流读取到内存,因为GetFileType方法需要一个字节数组作为输入参数。您可以使用File.WriteAllBytes方法以非常简单的方式将数组的字节写入磁盘,而不是再次访问原始流:

public Result UploadUserProfilePicture(Stream image)
{
    try
    {
        // Store bytes in a variable
        var bytes = CommonMethods.ReadToEnd(image);
        FileType fileType = bytes.GetFileType();

        Guid guid = Guid.NewGuid();
        string imageName = guid.ToString() + "." + fileType.Extension;
        var path = Path.Combine(@"C:\" + imageName);
        File.WriteAllBytes(path, bytes);
        return new Result
        {
            Success = true,
            Message = imageName
        };
    }
    catch(Exception ex)
    {
        return new Result
        {
            Success = false,
            Message = ex.ToString()
        };
    }
}

请注意,这意味着您可能会在内存中存储大量字节,就像您之前所做的那样。如果您可以在不将所有字节读入内存的情况下使用流更好,那么寻找可以处理流的GetFileType方法的替代方案是非常值得的。然后,您可以先将映像保存到临时文件,然后打开新的FileStream以发现正确的文件类型,以便重命名该文件。