비이미지 미디어 파일 다운로드 불가, S3 업로드 시 원본 파일명 유실

로컬 스토리지에 있는 비이미지 미디어 파일 또는 rake uploads:migrate_to_s3를 사용하여 S3로 마이그레이션된 파일은 업로드 링크를 클릭할 때 원래 파일명으로 다운로드됩니다. 반면 S3에 직접 업로드된 비이미지 미디어 파일은 새 탭에서 열리며 원래 파일명이 손실됩니다.

rake uploads:migrate_to_s3는 모든 비이미지 업로드에 대해 content_disposition을 설정합니다.

반면 S3로 업로드할 때는 비미디어 업로드 에만 content_disposition을 설정합니다.

수정 방법은 is_supported_media를 is_supported_image로 교체하는 것입니다(테스트 결과 의도대로 동작함).

3개의 좋아요

sam님, 이 수정이 필요한가요?

3개의 좋아요

아마도 @martin, 그 변경사항이 올바른지 어떻게 생각하시나요?

4개의 좋아요

이 수정이 맞는 것 같다고 _생각_합니다 – 제안하신 변경 사항을 로컬에서 테스트해 보고 문제가 없으면 PR을 올리겠습니다.

3개의 좋아요

다시 살펴보니, 해결책은 반대 방향으로 설정해야 한다고 생각합니다. uploads:migrate_to_s3 작업은 if !FileHelper.is_supported_media?(name) 조건을 사용해야 합니다. 비디오와 오디오에 content-disposition: attachment; filename=X 헤더를 붙이는 것은 합리적이지 않습니다. 이러한 파일은 Discourse 게시글 내에서 스트리밍되는 것이 아니라 다운로드되는 것이 아니지 않나요?

따라서 우리가 원하는 것은 다음과 같습니다:

content-disposition attachment 헤더 없음

  • 이미지
  • 비디오
  • 오디오

원본 파일명을 가진 content-disposition attachment 헤더 있음

  • 기타 모든 첨부파일/업로드 (PDF, TXT, CSV 등)

제가 놓치고 있는 부분이 있다면, 더 많은 정보나 예시를 자유롭게 추가해 주세요.

3개의 좋아요

믿어주세요, 저는 이 문제를 해결하기 위해 며칠을 보냈고, 처음에는 저도 이상하게 생각했습니다. 하지만 content-disposition: attachment; filename=X를 이미지 외의 모든 미디어 파일에 설정하는 것이 현재 _로컬 저장소_에서 미디어 파일이 서빙되는 방식을 완벽하게 _모방_합니다.

간단히 말하면, 아닙니다! 필요하면 원복싱(oneboxing)을 사용하여 스트리밍할 수 있지만, 로컬 또는 S3 경로인 [media_file](path_to_media_file)의 직접 다운로드 링크는 로컬 저장소에서와 마찬가지로(그리고 S3로 이관된 파일의 경우에도) _원본 파일명_을 사용하여 파일을 _다운로드_해야 합니다.

하지만 갑자기 S3로 직접 업로드한 파일의 경우 이것이 불가능해졌습니다: [media_file](S3_path_to_media_file) 링크는 새 탭에서 미디어 파일을 스트리밍합니다(원복싱이 수행하는 것이므로 불필요합니다). 또한 미디어 플레이어 컨트롤에서 다운로드를 시도해도 원본 파일명을 잃어버립니다.

로컬 호스팅 파일과 S3 호스팅 파일은 동일한 방식으로 동작해야 한다고 기대하는 것이 맞지 않나요? 동의하시죠? 당신의 제안대로라면 S3 호스팅 업로드의 경우, 새 파일뿐만 아니라 이관된 파일에 대해서도 기능이 완전히 반대로 작동하게 됩니다.

자세한 사례 파일과 왜 제 제안이 올바른지(즉, 로컬과 S3 모두에 호스팅된 업로드에 대해 동일한 기능을 유지하는지)에 대한 설명을 드립니다:

로컬에 호스팅된 파일

저는 1~10MB 크기의 음성 파일 5,000개 이상의 저장소를 가지고 있으며, 총 용량은 약 40GB입니다. 현재 이 파일들은 로컬 저장소에 호스팅되어 있으며, 이제 S3로 이전되고 있습니다(이것은 의도된 것이며, 제 3자 서비스에 호스팅하는 것을 원하지 않습니다). 성능 측면에서는 이미 상당히 잘 작동하고 있지만, 저장 비용 상승과 S3와 CDN 사용 옵션 때문에 S3로 이관하는 것이 합리적입니다.

이 파일들은 _크기_에 최적화되어 있으며 스트리밍을 위한 것이 아니라, 로컬에서 다운로드하여 듣기 위한 것입니다(대역폭/연결성이 제한된 클라이언트를 위해). 파일들은 일괄 업로드된 후, 각 SHA1 값으로 생성된 링크를 사용하여 원시 게시물에서 참조됩니다: [dl_link](https://discourse.forum.tld/uploads/default/original/3X/0/1/0123..sha1.mp3)이며, 파일의 직접 링크를 클릭하여 원본 파일명으로 다운로드할 수 있습니다(예시 여기 참조).

반면, 이 링크들이 _원복싱_된다면 여전히 Discourse 서버에서 직접 스트리밍할 수 있으며(플레이어 컨트롤에서 다시 원본 파일명으로 다운로드도 가능합니다).

S3로 이관된 파일

uploads:migrate_to_s3를 사용하여 업로드를 로컬 저장소에서 S3로 이관하면 두 가지 일이 발생합니다:

  • 이미지 외의 모든 업로드에 content-disposition: attachment; filename=X가 설정됩니다.
  • 원시 게시물 내의 직접 로컬 링크 [dl_link](https://discourse.forum.tld/uploads/default/original/3X/0/1/0123..sha1.mp3)가 S3 링크 [dl_link](https://cdn_url/uploads/original/3X/0/1/0123..sha1.mp3)로 대체됩니다.

이는 원복싱을 포함하여 원본 파일명을 가진 다운로드 링크까지 로컬 호스팅 업로드의 모든 측면을 모방합니다.

S3로 새로 업로드된 파일

  • 모든 미디어 파일에 content-disposition: attachment; filename=X가 설정되지 않습니다
  • 새로 업로드된 파일은 원시(raw)에서 short-url을 사용하여 참조되지만, cooked 링크는 여전히 https://cdn_url/uploads/original/3X/0/1/0123..sha1.mp3로 직접 가리킵니다.
  • short-url 링크나 수동으로 삽입된 S3 링크 [dl_link](https://cdn_url/uploads/original/3X/0/1/0123..sha1.mp3)를 클릭하면 파일이 다운로드되지 않고 새 탭에서 열립니다.

content-disposition이 설정되지 않기 때문에, 이제 미디어 파일이 로컬 저장소에서 서빙되는 방식과 다릅니다(원복싱은 여전히 작동하지만, 원본 파일명을 가진 다운로드 링크는 더 이상 사용할 수 없습니다).

추가 정보가 필요하시다면 알려주세요.

2개의 좋아요

정말 좋습니다. 추가적인 맥락을 모두 제공해 주셔서 감사합니다. 다음 주에 이 내용을 가지고 테스트를 해보고 PR을 올리도록 하겠습니다.

5개의 좋아요

곧 출시 예정인 최종 2.5 버전에도 포함될 가능성이 있을까요?

1개의 좋아요

솔직히 말해서, 다른 긴급한 업무 때문에 이 문제에 대해 더 자세히 살펴본 적이 없습니다. 이번 주에 시간을 확보해서 제대로 살펴보려고 합니다. 변경 사항이 사소한 것 같으니 오래 걸리지는 않을 것입니다. PR이 완료되면 다시 알려드리겠습니다.

4개의 좋아요

@md-misko 사용 사례를 확인했고, content-disposition을 수정한 후에도 오디오와 비디오를 정상적으로 스트리밍할 수 있습니다. 수정 작업이 진행 중이며 오늘 안에 머지될 예정입니다:

기다려 주셔서 감사합니다!

4개의 좋아요

이 주제는 3일 후 자동으로 닫혔습니다. 더 이상 답변을 남길 수 없습니다.