如何将流从HttpContent结果上载到Azure文件存储

时间:2017-05-19 19:50:17

标签: c# azure stream azure-storage azure-storage-blobs

我正在尝试从存储在我的数据库中的网址下载文件列表,然后将它们上传到我的Azure FileStorage帐户。我成功下载了文件,可以将它们转换为本地存储上的文件或将其转换为文本并上传。但是,在将类似pdf的内容转换为文本时,我会丢失数据,而且我不想将文件存储在托管此端点的Azure应用程序上,因为我不需要以任何方式操作文件。

我尝试使用Stream上的HttpContent方法从UploadFromStream对象上传CloudFile中的文件。每当运行此命令时,我都会收到InvalidOperationException消息"Operation is not valid due to the current state of the object."

我已尝试将原始Stream转换为MemoryStream,但这只会将空白文件写入FileStorage帐户,即使我将位置设置为{{}的开头也是如此{1}}。我的代码在下面,如果有人能指出我缺少哪些信息来完成这项工作,我将不胜感激。

MemoryStream

3 个答案:

答案 0 :(得分:1)

出现同样的问题,唯一有效的方法是将即将到来的流(在您的情况下,httpStream方法中为DownloadFile(FileLink fileLink))读取到字节数组并使用UploadFromByteArray (byte[] buffer, int index, int count)代替UploadFromStream

因此,您的WriteFile(FileLink fileLink)方法将如下所示:

public void WriteFile(string targetDirectory, string targetFilePath, Stream fileStream)
{
  var options = SetOptions();
  var newFile = GetTargetCloudFile(targetDirectory, targetFilePath);

  const int bufferLength= 600;
  byte[] buffer = new byte[bufferLength];
  // Buffer to read from stram This size is just an example

  List<byte> byteArrayFile = new List<byte>(); // all your file will be here
  int count = 0;

  try
  {
      while ((count = fileStream.Read(buffer, 0, bufferLength)) > 0)
         {
            byteArrayFile.AddRange(buffer);               
         }                    
         fileStream.Close();
   }

   catch (Exception ex)
   {
       throw; // you need to change this
   }

   file.UploadFromByteArray(allFile.ToArray(), 0, byteArrayFile.Count);
   // Not sure about byteArrayFile.Count.. it should work
}

答案 1 :(得分:0)

根据您的描述和代码,我建议您首先使用Steam.CopyTo将流复制到本地memoryStream,然后将MemoryStream上传到Azure文件存储。

更多细节,您可以参考以下代码:

我只是更改了DownloadFile方法来测试它。

Marshal.ReleaseComObject(rng)

            Dim strFileName As String = comm.GenerateFilename(strUser_Id, strVPN) & ".docx"

            ' Save the document.
            Dim filename As Object = Path.GetFullPath(strNewFilePath & strFileName)
            newDoc.SaveAs(FileName:=filename)

            ' Close.
            Dim save_changes As Object = False
            newDoc.Close(save_changes)
            WordApp.Quit(save_changes)

            Marshal.ReleaseComObject(newDoc)
            Marshal.ReleaseComObject(WordApp)

            rng = Nothing
            newDoc = Nothing
            WordApp = Nothing

            ' Let GC know about it 
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            GC.WaitForPendingFinalizers()

            ' save the file to database
            SaveFormat(filename, strUser_Id, strFamilyId.Trim, strVPN.Trim, DateTime.Now.ToString(), "application/vnd.ms-word", br_id, "doc")

            If File.Exists(filename) Then
                File.Delete(filename)
            End If

答案 2 :(得分:0)

我遇到了类似的问题,并且发现UploadFromStream方法仅适用于缓冲流。不过,我能够使用MemoryStream成功将文件上传到azure存储。我不认为这是一个非常好的解决方案,因为在将文件流的内容复制到内存之前将文件流的内容复制到内存资源,然后将其用于内存资源。我想出的是一种直接写入azure流的方法,使用OpenWriteAsync方法创建流,然后使用源流中的简单CopyToAsync

CloudStorageAccount storageAccount   = CloudStorageAccount.Parse( "YourAzureStorageConnectionString" );
CloudFileClient     fileClient       = storageAccount.CreateCloudFileClient();
CloudFileShare      share            = fileClient.GetShareReference( "YourShareName" );
CloudFileDirectory  root             = share.GetRootDirectoryReference();
CloudFile           file             = root.GetFileReference( "TheFileName" );

using (CloudFileStream fileWriteStream = await file.OpenWriteAsync( fileMetadata.FileSize, new AccessCondition(),
                                                                    new FileRequestOptions { StoreFileContentMD5 = true },
                                                                    new OperationContext() ))
{
    await fileContent.CopyToAsync( fileWriteStream, 128 * 1024 );
}