簡體   English   中英

如何將流從HttpContent結果上載到Azure文件存儲

[英]How to upload the Stream from an HttpContent result to Azure File Storage

我試圖從存儲在我的數據庫中的URL下載文件列表,然后將它們上傳到我的Azure FileStorage帳戶。 我成功下載了文件,可以將它們轉換為本地存儲上的文件或將其轉換為文本並上傳。 但是,在將類似pdf的內容轉換為文本時,我會丟失數據,而且我不希望將文件存儲在此端點所托管的Azure應用程序上,因為我不需要以任何方式操作文件。

我試圖使用UploadFromStream上的CloudFile方法從HttpContent對象上傳Stream的文件。 每當運行此命令時,我都會收到InvalidOperationException ,並顯示消息"Operation is not valid due to the current state of the object."

我也嘗試將原始Stream轉換為MemoryStream ,但這只是將一個空白文件寫入FileStorage帳戶,即使我將位置設置為MemoryStream的開頭。 我的代碼在下面,如果有人能指出我缺少哪些信息來完成這項工作,我將不勝感激。

public DownloadFileResponse DownloadFile(FileLink fileLink)
{
    string fileName = string.Format("{0}{1}{2}", fileLink.ExpectedFileName, ".", fileLink.ExpectedFileType);
    HttpStatusCode status;
    string hash = "";
    using (var client = new HttpClient())
    {
        client.Timeout = TimeSpan.FromSeconds(10); // candidate for .config setting
        client.DefaultRequestHeaders.Add("User-Agent", USER_AGENT);

        var request = new HttpRequestMessage(HttpMethod.Get, fileLink.ExpectedURL);
        var sendTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
        var response = sendTask.Result; // not ensuring success here, going to handle error codes without exceptions

        status = response.StatusCode;
        if (status == HttpStatusCode.OK)
        {
            var httpStream = response.Content.ReadAsStreamAsync().Result;

            fileStorage.WriteFile(fileLink.ExpectedFileType, fileName, httpStream);
            hash = HashGenerator.GetMD5HashFromStream(httpStream);
        }
    }

    return new DownloadFileResponse(status, fileName, hash);
}

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

public FileRequestOptions SetOptions()
{

    FileRequestOptions options = new FileRequestOptions();

    options.ServerTimeout = TimeSpan.FromSeconds(10);
    options.RetryPolicy = new NoRetry();

    return options;
}

public CloudFile GetTargetCloudFile(string targetDirectory, string targetFilePath)
{
    if (!shareConnector.share.Exists())
    {
        throw new Exception("Cannot access Azure File Storage share");
    }

    CloudFileDirectory rootDirectory = shareConnector.share.GetRootDirectoryReference();
    CloudFileDirectory directory = rootDirectory.GetDirectoryReference(targetDirectory);

    if (!directory.Exists())
    {
        throw new Exception("Target Directory does not exist");
    }

    CloudFile newFile = directory.GetFileReference(targetFilePath);

    return newFile;
}

有同樣的問題,只是它的工作方式是通過讀取來流(在您的情況下,它是httpStreamDownloadFile(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
}

根據您的描述和代碼,我建議您首先使用Steam.CopyTo將流復制到本地memoryStream,然后將MemoryStream上傳到azure文件存儲。

更多細節,您可以參考以下代碼:

我只是更改了DownloadFile方法來測試它。

     HttpStatusCode status;

                using (var client = new HttpClient())
                {
                    client.Timeout = TimeSpan.FromSeconds(10); // candidate for .config setting
                                                               // client.DefaultRequestHeaders.Add("User-Agent", USER_AGENT);

                    //here I use my blob file to test it              
                    var request = new HttpRequestMessage(HttpMethod.Get, "https://xxxxxxxxxx.blob.core.windows.net/media/secondblobtest-eypt.txt");
                    var sendTask =  client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
                    var response = sendTask.Result; // not ensuring success here, going to handle error codes without exceptions
                    status = response.StatusCode;

                    if (status == HttpStatusCode.OK)
                    {
                        MemoryStream ms = new MemoryStream();

                        var httpStream = response.Content.ReadAsStreamAsync().Result;

                        httpStream.CopyTo(ms);
                        ms.Position = 0;
                       WriteFile("aaa", "testaa", ms);
                     //   hash = HashGenerator.GetMD5HashFromStream(httpStream);
                    }
                }

我遇到了類似的問題,並且發現UploadFromStream方法僅適用於緩沖流。 然而,我能夠通過使用MemoryStream成功地將文件上傳到azure存儲。 我不認為這是一個非常好的解決方案,因為在將文件流的內容復制到內存之前將文件流的內容復制到內存資源,然后將其用於內存資源。 我想到的是一種直接寫入azure流的方法,而是使用OpenWriteAsync方法創建流,然后使用CopyToAsync的簡單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 );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM