Search code examples
angularerror-handlinghttpresponse

Why is my response error different from the one caught by error interceptor?


I have this API that throws an exception if the file size to be downloaded exceeds the max set.

@GET
    @Path("files")
    public Response getFile(@QueryParam("filePath") String filePath) throws IOException {
        File file = new File(filePath);

        long fileSizeKb = Math.max(file.length() / 1024, 1);

        if (fileSizeKb > APIServerProperties.MAX_DOWNLOADABLE_FILE_SIZE_KB) {
            String msg = MessageBundle.getMessage(MessageKeys.ERR_FILE_SIZE_EXCEEDED, String.valueOf(fileSizeKb),
                    String.valueOf(APIServerProperties.MAX_DOWNLOADABLE_FILE_SIZE_KB));
            System.out.println("msg: " + msg);
            throw new GeneralException(msg,
                    new FileSizeLimitExceededException(msg, fileSizeKb, APIServerProperties.MAX_DOWNLOADABLE_FILE_SIZE_KB));
        }

        // Read file content into byte array
        byte[] fileBytes = readFileContent(file);

        return Response.ok(fileBytes).header("Content-Disposition", "attachment; filename=" + file.getName()).build();
    }

It is being called by this angular function:

downloadFile(filePath: string) {
    this.migrationService.getFile(filePath).subscribe({
      next: (response) => {
        const fileContent: Uint8Array = new Uint8Array(response);
        const fileContentStr = new TextDecoder().decode(fileContent);

        const forwardSplit = filePath.split("/");
        const backwardSplit = forwardSplit[forwardSplit.length - 1].split("\\");
        let fileName = backwardSplit[backwardSplit.length - 1];

        const element = document.createElement("a");
        element.setAttribute(
          "href",
          "data:text/cvs;charset=utf-8," + encodeURIComponent(fileContentStr)
        );
        element.setAttribute("download", fileName);
        element.style.display = "none";
        document.body.appendChild(element);
        element.click();
        document.body.removeChild(element);
      },
      error: (err) => {
        console.log("err", err);
      },
    });
  }

All good so far. When I force the error, I get this as a response. This is what I need so I can display it properly. enter image description here

However, this is what I see in the console logs from the downloadFile function. enter image description here

Why am I not getting the response object and how do I fix it?


Solution

  • Saw this question which is quite similar to the problem I was having. It gave me an idea of what I had to do.

    I updated my downloadFile function's error handling. I processed the arrayBuffer similar to when I am reading the file content. This time, passing in the error object.

    downloadFile(filePath: string) {
        this.migrationService.getFile(filePath).subscribe({
          next: (response) => {
            const fileContent: Uint8Array = new Uint8Array(response);
            const fileContentStr = new TextDecoder().decode(fileContent);
            const forwardSplit = filePath.split("/");
            const backwardSplit = forwardSplit[forwardSplit.length - 1].split("\\");
            let fileName = backwardSplit[backwardSplit.length - 1];
            const element = document.createElement("a");
            element.setAttribute(
              "href",
              "data:text/cvs;charset=utf-8," + encodeURIComponent(fileContentStr)
            );
            element.setAttribute("download", fileName);
            element.style.display = "none";
            document.body.appendChild(element);
            element.click();
            document.body.removeChild(element);
          },
          error: (err) => {
            const buffer = new Uint8Array(err.error);
            const bufferStr = new TextDecoder().decode(buffer);
            const errorResponse = JSON.parse(bufferStr);
            const config = new MatDialogConfig();
            this.dialogRef = this.dialog.open(ErrorMessageComponent, config);
            this.dialogRef.componentInstance.msgObj = {
              errorMessage: errorResponse.statusText,
            };
          },
        });
      }