2
\$\begingroup\$

I am currently developing an e-commerce website where users can upload their photos to customise their products. The use case begins when the user selects a product from our website (e.g. shirt). After that, they will select the quantity and upload their photos. The client-side will then append the following fields to the using FormData: productId, productName and imageBlob. The imageBlob is the user uploaded images. I will then send these data over to my server-side (asp.net core) for sanitisation by checking the productId received with the database. I feel that there is a lot of improvement that can be done to my code but I just do not have the knowledge to do so. Is there anyone that can give feedback or help to improve my code?

Client-side (JavaScript)

function b64toBlob(b64Data, contentType, sliceSize) {
    contentType = contentType || "";
    sliceSize = sliceSize || 512;

    var byteCharacters = atob(b64Data);
    var byteArrays = [];

    for (
      var offset = 0;
      offset < byteCharacters.length;
      offset += sliceSize
    ) {
      var slice = byteCharacters.slice(offset, offset + sliceSize);

      var byteNumbers = new Array(slice.length);
      for (var i = 0; i < slice.length; i++) {
        byteNumbers[i] = slice.charCodeAt(i);
      }

      var byteArray = new Uint8Array(byteNumbers);

      byteArrays.push(byteArray);
    }

    var blob = new Blob(byteArrays, { type: contentType });
    return blob;
  }

  function imagetoblob(base64Image) {
    // Split the base64 string in data and contentType
    var block = base64Image.split(";");
    // Get the content type of the image
    var contentType = block[0].split(":")[1]; // In this case "image/gif"
    // get the real base64 content of the file
    var realData = block[1].split(",")[1]; // In this case "R0lGODlhPQBEAPeoAJosM...."

    // Convert it to a blob to upload
    return b64toBlob(realData, contentType);
  }

  const formData = new FormData();

  for (var i = 0; i < userProducts.length; i++) {
    formData.append("arr[" + i + "]", userProducts[i].productId);
    formData.append("arr[" + i + "]", userProducts[i].productName);
    formData.append(
      "arr[" + i + "]",
      imagetoblob(userProducts[i].base64Image)
    );
  }

Server-side (ASP.NET Ccore)

[AllowAnonymous]
[HttpPost("sanitizeUserCart")]
public async Task<IActionResult> sanitizeUserCart([FromForm] IFormCollection inFormData)
{

    List<Task<Product>> productTasks = new List<Task<Product>>();

    try
    {
        foreach (var key in inFormData.Keys)
        {
            if (key.Contains("arr"))
            {
                int i = 0;
                var id = int.Parse(inFormData[key][0]);
                var name = inFormData[key][1];
                var image = inFormData.Files[i];
                productTasks.Add(_productService.GetUserCart(id, name));
                i++;
            }

        }
        var productResults = await Task.WhenAll<Product>(productTasks);
        return new JsonResult(productResults);
    }
    catch (Exception ex)
    {
        // return error message 
        return BadRequest(new { message = ex.Message });
    }
}
\$\endgroup\$
  • \$\begingroup\$ I would suggest adopting a more strongly typed approach. You can use the code from this question as an inspiration. For now, your product server-side handling looks shady on too many levels. \$\endgroup\$ – Bohdan Stupak Jun 10 at 10:04
  • \$\begingroup\$ Hi @BohdanStupak May I know why is it "shady on too many levels"? What needs to be changed? \$\endgroup\$ – Issaki Jun 10 at 11:44
  • \$\begingroup\$ arr is some sort of magic string. you have to keep in mind that it should be synced on a client and on a backend. Your parsing logic is hard to comprehend. Looks rely on the fact that your files are sent in some sort of exact order, and it takes quite a lot of time to figure that out. Also, you actually never use the image var so I doubt if there any need to parse it. \$\endgroup\$ – Bohdan Stupak Jun 10 at 12:17
  • \$\begingroup\$ @BohdanStupak Thanks for the reply! As for your comment, "Looks rely on the fact that your files are sent in some sort of exact order". I am trying to avoid that but I do not know, the only way that I could think of is in exact order. Is there a better way to retrieve the data without following an order? \$\endgroup\$ – Issaki Jun 10 at 12:23
  • \$\begingroup\$ I do think that the best idea is to leave mapping to ASP.NET core as per my first comment \$\endgroup\$ – Bohdan Stupak Jun 10 at 13:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.