1

I'm attempting to move pdf files between two web services. To start, I successfully downloaded a file form the source service to local storage using await httpClient.GetStreamAsync(varPdfUrl) and then uploaded it to the destination service using File.OpenRead() which is commented out below. When I attempt to use await httpClient.GetStreamAsync(varPdfUrl) to load the StreamContent directly I get the following error.

Error Message: System.Net.Http.HttpRequestException: Error while copying content to a stream. ---> System.IO.IOException: Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host..

 var httpClient = new HttpClient();
 var request = new HttpRequestMessage(HttpMethod.Post, uploadResponse.url);
 var content = new MultipartFormDataContent();

  // Populate MultipartFormDataContent 
  content.Add(new StringContent(uploadResponse.fields.key), "key");
  content.Add(new StringContent(uploadResponse.fields.ContentType), "Content-Type");

  // Add File Stream
  string fileName = drawingTemp.ProjectNumber + "-" + drawingTemp.Title + ".pdf";

  //string localPath = @"C:\... \CMP\Drawing Downloads\";
  //var fileSteamLocalFile = new StreamContent(File.OpenRead(localPath + fileName));
  //content.Add(fileSteamLocalFile, "file", fileName);

   var fileSteam = new StreamContent(await httpClient.GetStreamAsync(drawingTemp.PdfUrl));
   content.Add(fileSteam, "file", fileName );

   content.Add(new StringContent(uploadResponse.uuid), "uuid");

   try
       {
           //Upload File to AWS
            request.Content = content;
            var responseUploadFileMsg = await httpClient.SendAsync(request);
       }
     

I guess all StreamContent objects are not created equal... please advise. Thanks!

UPDATE

I'm still unable to populate StreamContent with httpClient.GetStreamAsync() but as a work around I'm able to write the file to a project folder "wwwroot/Files" and then use File.OpenRead() to read the file and populate StreamContent. I would still appreciate any ideas as to why populating StreamContent directly with httpClient.GetStreamAsync() throws the error listed above.

    var httpClient = new HttpClient();
    var request = new HttpRequestMessage(HttpMethod.Post, uploadResponse.url);
    var content = new MultipartFormDataContent();

    // Add File Stream
    string fileName = drawingTemp.ProjectNumber + "-" + drawingTemp.Title + ".pdf";
    Stream fileSteam = await httpClient.GetStreamAsync(drawingTemp.PdfUrl);

   // Convert Stream to File and save temporarily to wwwroot/Files 
   string writeFullPath = @"wwwroot\Files\" + fileName;
                    
   if (!File.Exists(writeFullPath))
   {
      using var fileLocalPath = File.Create(writeFullPath);
      {
          fileSteam.CopyTo(fileLocalPath);
          fileSteam.Dispose();
      }
   }

   string readFullPath = Environment.CurrentDirectory + @"\wwwroot\Files\" + fileName;

  // Add File Stream to Content
  var fileSteamLocalFile = new StreamContent(File.OpenRead(readFullPath));
  content.Add(fileSteamLocalFile, "file", fileName);
                   
  content.Add(new StringContent(uploadResponse.uuid), "uuid");

  try
     {
        //Upload File to AWS
        request.Content = content;
        var responseUploadFileMsg = await httpClient.SendAsync(request);
        fileSteamLocalFile.Dispose();

       // Delete temp file 
       if (File.Exists(readFullPath))
       {
          File.Delete(readFullPath);
       }
Todd T
  • 185
  • 2
  • 9
  • Can you check the log file to get more details on the error? Also worth increasing timeout `httpClient.Timeout = TimeSpan.FromSeconds( – Talkhak1313 Mar 29 '23 at 03:46
  • On which exact line do you get this error? Are you sure the URL is working, can you download it in a browser? – Charlieface Mar 29 '23 at 12:00
  • I get the error on the last line when it attemtps httpClient.SendAsync(request). Here is the URL being passed in which I can download successfully via a browswer. https://storage.procore.com/v4/d/us-east-1/pro-core.com-staging/c67549b2-800a-47da-99b8-419804e3b01f_production_1679170331_c3161_p1.pdf?sig=0f7edb5e4089edf83cd351130f6c65d6005c2fdea602f721f5c67c2796fc2229 – Todd T Mar 29 '23 at 12:04
  • Talkhak, I tried the setting the Timeout but it still throws the error. The error occurs instantly so I don't think it's a timeout issue. The error is thrown in the browser so I'm not sure how to obtain more details other than posting the full error message which I can do if it will help. Here is a similar thread from 7 years ago but the suggestions did not makes sense to me and I figured they are probably outdated. https://stackoverflow.com/questions/33233780/system-net-http-httprequestexception-error-while-copying-content-to-a-stream – Todd T Mar 29 '23 at 12:37
  • The problem isn't StreamContent - that's what you're using in both cases. It's the remote server that's closing the connection, not HttpClient. The actual problem is that the code is trying to send contents that are still being downloaded from a slow and possibly unstable network connection directly to another network connection. Any hiccup or delay in the download stream will impact the upload as well. If one of the two remote servers has a short timeout, it can fault and close the connection – Panagiotis Kanavos Mar 31 '23 at 12:35
  • 1
    Storing to a local file isn't a hack, it's a reliability technique. You don't have to store to `wwwroot` either, you can use `Path.GetTempPath` to get the current temp folder or create a folder specifically for this job – Panagiotis Kanavos Mar 31 '23 at 12:37
  • Many services allow partial uploads using the `Range` header, PATCH or specific APIs, which means you may be able to restart failed uploads as long as the file is still on disk. That includes cloud services like AWS S3 and Azure blob storage – Panagiotis Kanavos Mar 31 '23 at 12:42
  • I really appreciate the feedback and will leverage Path.GetTemPath. Stepping through the code, the Write/Read appears sub-second so semi-confident it won't slow me down. Next test will be 1K+ records and once complete I'll give an update as to the the results. – Todd T Apr 03 '23 at 23:10

0 Answers0