User-Agent 분기 없이 일본어 파일 이름으로 파일 다운로드(이론 편)

10230 단어 PHP
일본어로 파일 이름을 다운로드할 수 있도록 User-AgentContent-Disposition를 통해 헤더filename의 형식과 문자 코드를 바꾸는 방법1을 알게 되었습니다. 이번에는 User-Agent에 의존하지 않고 브라우저를 교차시켜 일본어 파일 이름을 다운로드하는 방법을 소개하고 싶습니다.

개요

  • User-Agent 브랜치Content-Disposition를 통해 헤더를 보내지 않음
  • 브라우저를 사용하여 URL에서 파일 이름을 결정하는 방법
  • 다운로드 URL의 PATHINFO에 일본어 파일 이름 입력
  • 브라우저에서 파일을 저장할 때 무엇을 참고하시겠습니까?


    브라우저가 웹 페이지의 자원을 로컬로 저장할 때 반드시 파일 이름을 추가해야 하는데, 브라우저는 도대체 무엇을 참고하여 파일 이름을 결정합니까?
    먼저 HTML<title> 태그의 문자열 + 를 고려합니다.예)

    둘째, 이미지 파일이 URL에 포함된 파일 이름인 HTML이 아닌 경우

    마지막으로 Content-Disposition 헤더filename의 값입니다.
    아마도 다른 것이 있을 것이다. 대체로 이 세 가지 중의 하나일 것이다.
    두 번째 파일 이름을 결정하는 방법에 착안하고 싶습니다.위의 예에서 영어의 파일 이름은 Web-browser이다usage_on_Wikimedia.svg이지만 URL에서 URL 인코딩만 하면 일본어를 포함할 수 있기 때문에 일본어 파일 이름을 URL 경로에 포함시키고 싶습니다.

    $_SERVER를 이용해서 ['PATH INFO']


    PHP의 경우 PHP 파일 이름 뒤에 사선을 더하면 쿼리 열 앞에 있는 경로가 $_SERVER['PATH_INFO']에 저장됩니다.
    예를 들어 방문http://example.com/index.php/foo/bar/buz?hoge=123의 경우 index.php 설정$_SERVER['PATH_INFO'] = '/foo/bar/buz'.
    이 방법을 활용하면PATH_INFO에 다운로드용 파일 이름을 설정하면 된다.예를 들어 index.php/請求書-2016年02月-1432.pdf?invoice_id=1432와 같은 URL로 PDF를 생성하면 브라우저는 PDF를 請求書-2016年02月-1432.pdf로 저장합니다.
    서버측 index입니다.php는 PATH_INFO의 값을 무시할 수 있지만 URL은 사용자가 결정하기 때문에 파일 이름을 함부로 붙이지 않으려면 $_GET['invoice_id']를 키로 요청한 데이터에 비해 개발자가 의도한 파일 이름과 동일한지 검사할 수 있다PATH_INFO.

    샘플 코드: 일본어 파일 이름으로 저장된 예


    다음 샘플 코드는 웹 페이지의 자원을 임의의 파일 이름으로 저장하는 예입니다.볼 수 있지만 User-Agent 분기가 없습니다.
    download.php
    $filename = isset($_SERVER['PATH_INFO']) ? trim($_SERVER['PATH_INFO'], '/') : '';
    $file = isset($_GET['file']) ? $_GET['file'] : '';
    if (empty($filename) or empty($file)) {
        header('HTTP', null, 400);
        header('Content-Type: text/plain');
        die('Invalid request');
    }
    
    // ファイルの内容をとってくる処理
    $contents = @file_get_contents("http://$file"); // ここはもう少し安全にする必要があるがサンプルなので割愛
    if ($contents === false) {
        header('HTTP', null, 500);
        header('Content-Type: text/plain');
        die(error_get_last()['message']);
    }
    
    // ファイルをダウンロードさせる処理
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment');
    header('Content-Length: ' . strlen($contents));
    echo $contents;
    
    이 샘플의 사용 방법에 대해 사용자는 http://example.com/download.php/[ファイル名]?file=[リソース名] 등 URL에 접근해서 사용할 수 있다.파일 이름은 다운로드할 때의 파일 이름을 지정하고, 자원 이름은 URL에서 프로토콜을 제외하는 부분을 지정합니다.2
    예를 들어 Qita의Mardown 메모 태그 Mardown 파일을 다운로드하려면 다음 URL을 방문하십시오.
    http://example.com/download.php/Markdown%E8%A8%98%E6%B3%95%20%E3%83%81%E3%83%BC%E3%83%88%E3%82%B7%E3%83%BC%E3%83%88.md?file=qiita.com/Qiita/items/c686397e4a0f4f11683d.md
                                    ^ この部分がダウンロード向けファイル名
    
    이 URL에 액세스했습니다. 브라우저의 동작은 다음과 같습니다.
    Google Chrome은 의도한 파일 이름으로 문제없이 저장됩니다.

    Firefox도 괜찮을 것 같아요.

    사파리도 괜찮아.

    우려되는 IE11도 문제가 없는 것으로 보인다.

    URL 인코딩 고려 사항


    URL에 일본어 파일 이름을 포함하려면 URL 인코딩이 필요하지만 인코딩할 함수는 사용rawurlencode입니다.urlencode 함수를 사용하면 반각 공간+이 인코딩되지만 파일 이름은 직접 표시+됩니다.

    라우터를 사용하면 URL이 더 선명해집니다.


    이번에 소개된 샘플 코드는 쿼리 열에서 파일 자원을 찾는 것으로, MVC 프레임워크의 라우터를 사용하면 URL이 더욱 뚜렷해진다.
    예를 들어, Silex에서 다음 라우트를 설정한 경우 /invoices/1432/請求書-2016年02月-1432.pdf 등의 URL을 통해 파일을 다운로드할 수 있습니다.
    $app = new Silex\Application(); 
    
    $app->get('/invoices/{invoiceId}/{filename}', function($invoiceId, $filename) use($app) { 
        // ここで $invoiceId から請求データを取得し、PDFを出力する
    })->assert('filename', '.+\.pdf');
    
    $app->run(); 
    

    끝맺다


    이번에는 User-Agent에서 분기되지 않는 일본어 파일 이름을 다운로드하는 방법에 대해 설명합니다.검증된 브라우저가 많지 않기 때문에 정상적으로 실행되지 않는 브라우저를 보고할 수 있다면 다행입니다.
    계속: User-Agent 분기 없이 일본어 파일 이름으로 파일 다운로드(전체 버전)
    [일본어 파일 이름에 해당] 파일을 간단하게 다운로드하는 함수 - Qita  
    이 코드는 단지 일본어 URL을 간단하게 테스트하기 위해서이며, '파일 내용 추출 처리' 부분은 어떤 URL에서도 얻을 수 있지만, 실제로는 더욱 구속적인 설치가 더욱 안전하다.실천적인 실현은 @mpyw선생님의 User-Agent 분기 없이 일본어 파일 이름으로 파일 다운로드(전체 버전)을 보십시오. 

    좋은 웹페이지 즐겨찾기