Skip to content

Use File.binread and an explicit filename when sending court report .docx #7099

Description

@compwron

What

CaseCourtReportsController#show sends the generated .docx with two small problems:

format.docx do
  @casa_case.latest_court_report.open do |file|
    # TODO test this .read being present, we've broken it twice now
    send_data File.read(file.path), type: :docx, disposition: "attachment", status: :ok
  end
end

1. File.read should be File.binread. File.read reads in text mode, so binary docx content comes back tagged UTF-8:

File.read     encoding=UTF-8      length=365389  bytesize=379838  valid_encoding?=false
File.binread  encoding=ASCII-8BIT length=379838  bytesize=379838

Note length and bytesize disagree by ~14KB. Nothing in the current stack misuses length over bytesize — verified that Content-Length comes out correct and the download is byte-exact — so this is not currently causing a bug. But handing send_data a UTF-8-tagged string full of invalid UTF-8 is asking for trouble, and that line already carries a we've broken it twice now comment (see #1253, and 17883f4 "fix: court report document show").

2. send_data has no filename:. With only disposition: "attachment" and no filename, the browser derives the download name from the URL path. That mostly works, but it is incidental rather than intentional, and it breaks down for case numbers containing characters that get escaped in a URL. A stakeholder-reported file in #7093 arrived named _C-15-JV-24-191.docx with a leading underscore that does not appear in the case number.

Suggested change

send_data File.binread(file.path),
  type: :docx,
  filename: "#{@casa_case.case_number}.docx",
  disposition: "attachment",
  status: :ok

Testing

Worth resolving the existing TODO at the same time — there is currently no assertion that the downloaded bytes match the stored blob. Something like: generate a report, GET the .docx link, and assert response.body.bytesize == blob.byte_size, that the body starts with PK\x03\x04, and that Content-Disposition carries the expected filename.

Context

Found while debugging #7093. File.read was briefly a suspect for the corrupt-download bug there and was ruled out — the real cause was zip64 (#7098). Filing separately so it does not get lost.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type: BugDefect or regressionrubyTouches Ruby code📊 ReportsReports pulled by admins and supervisors

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions