为 AWS C# S3 SDK 使用内存流而不是文件流而不将完整文件写入 S3

Posted

技术标签:

【中文标题】为 AWS C# S3 SDK 使用内存流而不是文件流而不将完整文件写入 S3【英文标题】:Using memory stream instead of filestream for AWS C# S3 SDK not writing full file to S3 【发布时间】:2021-12-28 14:58:19 【问题描述】:

我有一些用于在 AWS S3 存储桶上创建文件的代码。当我使用文件流时,它工作正常并且所有数据都存在。当我使用内存流时,文件中的一些 xml 数据丢失了。这是我正在运行的代码:

internal void WriteDataContractToFile(object data, string filename)
    
        string path = @"C:\Jenova\restfulengine\RESTfulEngine\App_Data\requests\" + filename;
        try
        
            using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite))
            
                using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8))
                
                    DataContractSerializer dcs = new DataContractSerializer(data.GetType());
                    writer.WriteStartDocument();
                    dcs.WriteObject(writer, data);
                
            
            var uploadRequest = new TransferUtilityUploadRequest();
            uploadRequest.FilePath = path;
            uploadRequest.Key = filename;
            uploadRequest.BucketName = bucketName;
            transferUtility.Upload(uploadRequest);

            //METHOD WITH MEMORY STREAM THAT DOESNT WORK

            using (MemoryStream stream = new MemoryStream())
            
                using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8))
                
                    DataContractSerializer dcs = new DataContractSerializer(data.GetType());
                    writer.WriteStartDocument();
                    dcs.WriteObject(writer, data);
                    var uploadRequest1 = new TransferUtilityUploadRequest();
                    uploadRequest1.InputStream = stream;
                    uploadRequest1.Key = filename;
                    uploadRequest1.BucketName = bucketName;
                    transferUtility.Upload(uploadRequest);
                
            
        
        
    

当我对文件流使用第一种方法时,所有数据都存在于我在 S3 中创建的文件中。当我使用内存流时,我错过了文件的结尾:

并且缺少文件末尾:

它应该是这样的:

有没有人看到我做错了什么?为什么内存流截断数据对我来说没有意义。即使我将该内存流写入本地文件以测试数据也不完整,所以我有点不知所措,感谢任何建议!

【问题讨论】:

【参考方案1】:

您在流完全写入之前上传。可能是在您处置 writer 时写入最后一个缓冲区。

所以:

using (MemoryStream stream = new MemoryStream())

    using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8))
    
        DataContractSerializer dcs = new DataContractSerializer(data.GetType());
        writer.WriteStartDocument();
        dcs.WriteObject(writer, data);
    

    var uploadRequest1 = new TransferUtilityUploadRequest();
    uploadRequest1.InputStream = stream;
    uploadRequest1.Key = filename;
    uploadRequest1.BucketName = bucketName;
    transferUtility.Upload(uploadRequest);

使用XmlDictionaryWriter.CreateTextWriter(Stream, Encoding, Boolean)false 作为最后一个参数,让它保持流打开。

【讨论】:

我之前尝试过(抱歉应该在问题详细信息中包含它)。问题是当我将 uploadRequest 代码放在编写器块之外时,它说我正在尝试在它关闭后访问流。有没有办法在写入后保持打开状态? XmlDictionaryWriterownsStream 有一个重载,您可以传递 false 让它保持流打开。 成功了!非常感谢您的帮助,您可以挽救生命!

以上是关于为 AWS C# S3 SDK 使用内存流而不是文件流而不将完整文件写入 S3的主要内容,如果未能解决你的问题,请参考以下文章

您可以使用流而不是本地文件上传到 S3 吗?

golang aws-sdk-go 之 s3 服务

如何使用 aws-java-sdk 从 S3 逐块读取文件

如何将 Java OutputStream 上传到 AWS S3

为特定文件设置 AWS S3 过期时间

如何使用 aws-sdk 获取 AWS S3 上文件的 URL?