如何附加到Azure存储文件共享中的文件?

时间:2016-05-18 15:48:57

标签: file append azure-storage

我想将条目写入存储在Azure文件存储中的日志文件中。我目前有这个:

var log = "My log entry";

var client = _storageAccount.CreateCloudFileClient();
var share = client.GetShareReference(Config.LogShare);
share.CreateIfNotExists();
var root = share.GetRootDirectoryReference();
var logfile = root.GetFileReference("log.txt");
if (!logfile.Exists()) logfile.Create(0);

// What goes here to append to the file...?

我可以看到很多关于如何使用Blob执行此操作的示例,或者如何上传整个文件,但我如何才能附加到现有文件?

我试过这个:

var buffer = Encoding.GetEncoding("UTF-8").GetBytes(log.ToCharArray());

using (var fileStream = logfile.OpenWrite(0)) {
    fileStream.Write(buffer, (int)logfile.Properties.Length, buffer.Length);
}

但后来我收到了这个错误:

The remote server returned an error: (416) The range specified is invalid for the current size of the resource..

4 个答案:

答案 0 :(得分:1)

Azure文件存储REST API不支持附加到现有文件。要实现此目的,请将文件共享作为驱动器安装到您的计算机上,并像简单的本地文件一样附加到文件中。

实际上,我认为您不需要为上面的代码添加功能。您可以在CloudFile.OpenWrite()/ CloudFile.Create()中指定文件大小,或尝试CloudFile.UploadFromStream()而不是CloudFile.OpenWrite()。

答案 1 :(得分:0)

我设法自己解决这个问题。您只需要根据要写入的新字节数增加文件大小,然后将新数据写入文件末尾的新空白区域,如下所示:

var client = _storageAccount.CreateCloudFileClient();
var share = client.GetShareReference(Config.LogShare);
share.CreateIfNotExists();
var root = share.GetRootDirectoryReference();
var logfile = root.GetFileReference("log.txt");
if (!logfile.Exists()) logfile.Create(0);

var buffer = Encoding.UTF8.GetBytes($"{log}\r\n");

logfile.Resize(logfile.Properties.Length + buffer.Length);

using (var fileStream = logfile.OpenWrite(null)) {
    fileStream.Seek(buffer.Length * -1, SeekOrigin.End);
    fileStream.Write(buffer, 0, buffer.Length);
}

答案 2 :(得分:0)

此错误也可能是由于多线程访问。 我敢打赌,如果您在访问文件之前尝试锁定文件,则不会遇到此问题。 有许多方法可以更新文件。 因为你已经设法获得共享,根,文件夹和文件..这是我的代码的一部分,对我有用。

if (!fileLock.IsWriteLockHeld) fileLock.EnterWriteLock();


        try
        {
            using (var stream = new MemoryStream(content, false))
            {
                file.UploadFromStream(stream, null, options);
            }
        }
        catch (Exception ex)
        {
            File.AppendAllText(FileName, ex.ToString());
        }
        finally
        {
            if (fileLock.IsWriteLockHeld)
                fileLock.ExitWriteLock();
        }

将fileLock声明为:

  protected ReaderWriterLockSlim fileLock = new ReaderWriterLockSlim();

话虽如此,我并不是说这是有史以来最好的方式。 我希望你记住的两件事: 1 - 锁定可能被多个线程访问的资源(这在AZURE中很常见) 2-熟悉Azure提供的异步方法..在它们适合的时候使用它们。

回到原来关于附加到现有文件的问题。 CloudFile的所有方法都将覆盖现有文件。云文件不适用于频繁编写,如果您经常对其进行编写,添加lock对性能的影响,它们确实会影响性能,它们会非常糟糕。

云文件旨在一劳永逸地存储大量数据,如果您想添加另一个批量,您可以选择创建另一个文件。 将所有数据与客户端一起保存,直到达到一定的大小,并创建一个算法来选择文件名并一次上传所有文件。

答案 3 :(得分:0)

您可以使用blob https://blogs.msdn.microsoft.com/windowsazurestorage/2015/04/13/introducing-azure-storage-append-blob/

执行此操作

羞耻它也不能用于文件