0

This is a beginners question. I have an API that is supposed to return a list of "MyContent". When I call the API from my test device it takes too long to load the byte array. It takes around 7 seconds on my iphone and 5 on the MVC app that I use for testing. I know that it is the byte array that is slowing everything down.

Below is my code. Is there anything I can do to my code that will speed things up? Other applications on my test device loads super fast so it should not be the bandwidth?

    public class MyContent
    {
       public byte[] Content; 
       public string Name;
    }



    [Route("/GetPicturesFromBlobStorage")]
    [HttpPost]
    [AllowAnonymous]
    public async Task<IActionResult> GetPicturesFromBlobStorageAsync([FromBody] List<string> filenames)
    {
        var files = new List<MyContent>();
        
        // here I have a loop that fills the "files" property. 

        var str = JsonConvert.SerializeObject(files);
        
        return Ok(str);

    }

This is the Xamarin.iOS code:

        var responseIng = await client.PostAsJsonAsync(url, files); // THIS IS THE LINE THAT TAKES FOREVER.

        String urlContentsIng = await responseIng.Content.ReadAsStringAsync();

UPDATE:

I changed so that I do not use json:

 public async Task<FileContentResult> GetPicturesFromBlobStorageAsync([FromForm] string filename)
    {
        var stopWatch5 = Stopwatch.StartNew();

        AzureStorageConfig config = new AzureStorageConfig();
        config.AccountName = "xxx";
        config.AccountKey = "xx"
        config.stagecontainer = "xx";

        var sasToken =
           _azureStorageBlobOptionsTokenGenerator.GenerateSasToken(
           config.stagecontainer);

        var storageCredentials =
                new StorageCredentials(
                    sasToken);

        var cloudStorageAccount =
            new CloudStorageAccount(storageCredentials, config.AccountName, null, true);

        var cloudBlobClient =
            cloudStorageAccount.CreateCloudBlobClient();

        var cloudBlobContainer =
        cloudBlobClient.GetContainerReference(config.stagecontainer);

        var blobName = filename;

        var cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(blobName);

        var stream = new MemoryStream();

        await cloudBlockBlob.DownloadToStreamAsync(stream);
        byte[] bytes = stream.ToArray();
        var time = stopWatch5.Elapsed.TotalSeconds;

        return File(bytes, "image/jpeg", filename);

    }

And this is my client call to the API

            var bag = new System.Collections.Concurrent.ConcurrentBag<object>();
        var tasks = files.Select(async file => 
        {
            var multiFormCat = new MultipartFormDataContent();
            multiFormCat.Add(new StringContent(file), "filename");
            var responseIng = await client.PostAsync(url, multiFormCat);

            var content = await responseIng.Content.ReadAsByteArrayAsync();
        });
        await Task.WhenAll(tasks);

It still takes around 4-5 seconds. Is there anything more I can do to improve performance?

Malin
  • 145
  • 7
  • You can compress the files and then send them over the network if you are not worried about the quality or you can try this https://stackoverflow.com/questions/26038856/how-to-return-a-file-filecontentresult-in-asp-net-webapi – ShubhamWagh Dec 26 '22 at 13:09
  • Sending files inside json is not a good idea, since you pay 33% space overhead + CPU time encoding and decoding to base64. Send them to client using multipart form data instead. This will also allow your client to save the files to filesystem right during the receiving process without loading them (in full) in memory first. – Evk Dec 26 '22 at 13:28
  • don't use json. If your client knows which files it wants, requesting each one individually is probably a better approach. If the files are already compressed images using gzip probably won't help much either – Jason Dec 26 '22 at 13:32
  • @Evk Oh okay thank you for your explanation. Do you have an example of how to return MultipartForm data, the only SO posts I can find is for file upload to API. Not to return multipart form – Malin Dec 26 '22 at 16:14
  • I messed up upload with download. For download it would be easier to not put multiple files in response but use separate request for each file, all at once (in parallel) and return file via File() asp.net call (still no json). You can return multiple files but it's not easy with asp.net api (unless you zip them into single file and return that). – Evk Dec 26 '22 at 17:03
  • @Evk Thank you! I updated my question accordingly. It still takes around 4-5 seconds. Would you mind having another look to see if there is anything else I can do? – Malin Dec 27 '22 at 09:50
  • @WandererAboveTheSea Thank you, I am worried about the quality. I looked at the post that you suggested but wasn't able to get it to work. Do you think that it is faster than the code that I updated my question with? – Malin Dec 27 '22 at 09:52
  • @Jason Thank you! I updated my question. Would you mind having a look to see if there is anything else I could do? :) – Malin Dec 27 '22 at 09:52
  • And how are you using those images on client? Also what's their size and how many of them you download at once? – Evk Dec 27 '22 at 10:36
  • @Evk I download one at a time, but ten in total. I am displaying the images in my Xamarin.iOS app. It's the downloading of the images that takes time. The size is around 3 MB. – Malin Dec 27 '22 at 11:58
  • And how long does it take to download from azure (I see stopwatch in the code)? – Evk Dec 27 '22 at 12:36
  • @Evk 0,75 seconds last I checked! – Malin Dec 27 '22 at 12:41

0 Answers0