3

I have a complex object parameter that I need to send as post, as it could be too long for querystring. The post call is asking to have an excel file dynamically generated and then downloaded asynchronously. But all of this is happening inside of a react application. How does one do this using axios.post, react, and webapi? I have confirmed that the file does generate and the download up to the response does come back, but I'm not sure how to actually open the file. I have a hidden iframe that I'm trying to set the path, src, of the file to, but I dont know what response property to use.

// webapi
[HttpPost]
public HttpResponseMessage Post([FromBody]ExcelExportModel pModel)
{
    var lFile = ProductDataModel.GetHoldingsExport(pModel);
    var lResult = new HttpResponseMessage(HttpStatusCode.OK);
    lResult.Content = new ByteArrayContent(lFile);
    lResult.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
        FileName = "HoldingsGridExport.xls"
    };

    lResult.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

    return lResult;
}

// client side api
static getHoldingsExport({ UserConfigurationID, UserID, Configurations, ViewName, SortModel, FilterModel, UserConfigType, IsDefault, LastPortfolioSearchID = null, ProductId }) {
    const filterModel = JSON.stringify(FilterModel); // saving as string as this model is dynamically generated by grid out of my control
    const sortModel = JSON.stringify(SortModel);

    let params = JSON.stringify({
        UserConfigurationID,
        UserID,
        Configurations,
        ViewName,
        filterModel,
        sortModel,
        UserConfigType,
        IsDefault,
        LastPortfolioSearchID,
        ProductId
    });

    return axiosInstance.post("/api/HoldingsExport", params);
}

// client side app call to get file
HoldingsApi.getHoldingsExport(config)
    .then(function(response) {
        debugger;
        let test = response;
    })
    .catch(error => {
        toastr.success('Failed to get export.');
    });
Muhammed Shevil KP
  • 1,404
  • 1
  • 16
  • 21
David Choi
  • 6,131
  • 10
  • 28
  • 28

2 Answers2

4

This is how I've achieved file downloads by POSTing via Axios:

Axios.post("YOUR API URI", {
    // include your additional POSTed data here
    responseType: "blob"
}).then((response) => {
    let blob = new Blob([response.data], { type: extractContentType(response) }),
        downloadUrl = window.URL.createObjectURL(blob),
        filename = "",
        disposition = response.headers["content-disposition"];

    if (disposition && disposition.indexOf("attachment") !== -1) {
        let filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/,
            matches = filenameRegex.exec(disposition);

        if (matches != null && matches[1]) {
            filename = matches[1].replace(/['"]/g, "");
        }
    }

    let a = document.createElement("a");
    if (typeof a.download === "undefined") {
        window.location.href = downloadUrl;
    } else {
        a.href = downloadUrl;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
    }
}).catch((error) => {
    // ...
});
awj
  • 7,482
  • 10
  • 66
  • 120
1

Just in case the above solution does not serve you quite well, here is how I could be able to download videos that are hosted on S3 AWS buckets,

const handleDownload = () => {
    const link = document.createElement("a");
    link.target = "_blank";
    link.download = "YOUR_FILE_NAME"
    axios
      .get(url, {
        responseType: "blob",
      })
      .then((res) => {
        link.href = URL.createObjectURL(
          new Blob([res.data], { type: "video/mp4" })
        );
        link.click();
      });
  };

And I trigger handleDownload function in a button with onClick.

The url in the function has the video URL from S3 buckets