【问题标题】:C# - Having problems with processing a Stream more than onceC# - 多次处理流时出现问题
【发布时间】:2016-02-18 10:21:59
【问题描述】:

我有一个 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 字节。

我尝试过: 用另一种方法转换为字节,只返回文件类型,但原来的位置仍然在最后。 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#? 作为问题的答案

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

【问题讨论】:

  • 为什么说不能发送其他参数?您系统的哪个部分施加了这样的限制?
  • @IgorLabutin 当我尝试向接收方法public Result UploadUserProfilePicture(Stream image) 添加另一个参数并尝试在服务上执行任何方法时,我收到错误Operation 'UploadUserProfilePicture' in contract 'IMobileService' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body.

标签: c# wcf stream


【解决方案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 以发现正确的文件类型,以便您可以重命名文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多