Skip to content

Conversation

@JosePineiro
Copy link

This refactor improves AsyncFileResponse::AsyncFileResponse(File content, const String &path, const char *contentType, bool download, AwsTemplateProcessor callback) The updated implementation:

  • Replaces the use of String::endsWith() with a more efficient memcmp() check for gzip file suffix.
  • Fix the download of precompresed archives. The old behavior was wrong.
  • Simplifies content-disposition header generation using consistent logic for both inline and download cases.

Overall, the refactor enhances performance slightly and ensures more consistent behavior when serving compressed downloadable files.

This refactor improves AsyncFileResponse::AsyncFileResponse(File content, const String &path, const char *contentType, bool download, AwsTemplateProcessor callback)
The updated implementation:
- Replaces the use of String::endsWith() with a more efficient memcmp() check for gzip file suffix.
- Fix the download of precompresed archives. The old behavior was wrong.
- Simplifies content-disposition header generation using consistent logic for both inline and download cases.

Overall, the refactor enhances performance slightly and ensures more consistent behavior when serving compressed downloadable files.
@JosePineiro
Copy link
Author

JosePineiro commented Jul 23, 2025

Async FileResponse(File content, const String &path, const char *content Type, bool download, AwsTemplateProcessor callback)
content = the file image.jpg.gz
path = image.jpg
download = true

In this case, a compressed file is downloaded with the name of an uncompressed file and without setting ContentEncoding = gzip.

This PR adds ContentEncoding = gzip when necessary.

@me-no-dev
Copy link
Member

This PR needs considerable testing before it get's approved. Maybe if it was split into string manipulations and gzip changes, it would have been easier to deal with.

This comment was marked as outdated.

Copy link
Member

@mathieucarbou mathieucarbou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will move the pr to draft as it is a proposal still requiring some work and testing for all possible use cases (download = true|false + request of file download or web resources + variants on FS of gzipped files or not)

@mathieucarbou mathieucarbou marked this pull request as draft July 23, 2025 12:06
JosePineiro and others added 3 commits July 23, 2025 22:06
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@JosePineiro
Copy link
Author

JosePineiro commented Jul 24, 2025

Bug:
Async FileResponse(File content, const String &path, const char *content Type, bool download, AwsTemplateProcessor callback)
content = the file image.jpg.gz
path = image.jpg
download = true

In this case, a compressed file is downloaded with the name of an uncompressed file and without setting ContentEncoding = gzip.

I've simplified the PR. Only one line has been changed, which fixes this bug.
If you need further explanation, please let me know.

@JosePineiro JosePineiro marked this pull request as ready for review July 24, 2025 02:06
@mathieucarbou
Copy link
Member

mathieucarbou commented Jul 24, 2025

In this case, a compressed file is downloaded with the name of an uncompressed file and without setting ContentEncoding = gzip.

That's the corner use case I was talking about in a previous PR comment I suppose ?.

I agree with it, though it changes a little the behavior ? Maybe in the case of a file manager where image.png sits next to image.png.gz and user wants to download image.png, not image.png.gz. In this case, image.png.gz will be downloaded in place of image.png ?

I would vote in accepting this behavior change since most of the usage in a MCU is to put a gz fiel to be served compressed.

@mathieucarbou mathieucarbou requested a review from Copilot July 24, 2025 09:45
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This refactor optimizes the AsyncFileResponse constructor by improving gzip file handling and content-disposition header generation. The changes focus on fixing the logic for serving precompressed archives and enhancing performance through more efficient string comparisons.

  • Removes the !download condition from gzip file detection logic to fix handling of precompressed downloadable files
  • Replaces inefficient String::endsWith() calls with memcmp() for better performance (based on description)
  • Simplifies content-disposition header generation for consistent inline/download behavior

@mathieucarbou
Copy link
Member

@me-no-dev : can you please have a look again ? PR looks good to me. Thanks!

@mathieucarbou mathieucarbou merged commit ec133bb into ESP32Async:main Aug 4, 2025
33 checks passed
@JosePineiro JosePineiro deleted the refactor/async-file-response-handling branch August 19, 2025 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants