为了让客户端的用户能够上传文件,我们必须在用户界面中提供一个表单用于提交上传文件的请求。由于上传的文件是一种特殊数据,不同于其它的post数据,所以我们必须给表单设置一个特殊的编码:
以上的enctype属性,你可能不太熟悉,因为这常常会被忽略掉。但是,如果http post请求中既有常规数据,又包含文件类数据的话,这个属性就应该显示加上,这样可以提高针对各种浏览器的兼容性。
上述文件字段在各种浏览器中可能表现会有所不同。对于大多数的浏览器,上述字段都会被渲染成一个文本框加上一个浏览按钮。这样,用户既可以自行输入文件的路径到文本框中,也可以通过浏览按钮从本地硬盘上选择所要上传的文件。但是,在苹果的Safari中,貌似只能使用浏览这种方式。当然,你也可以自定义这个上传框的样式,使它看起来比默认的样式优雅些。
提示:可以通过php.ini中的upload_max_filesize来设置允许上传文件的最大值。另外,还有一个post_max_size也可以用来设置允许上传的最大表单数据,具体意思就是表单中各种数据之和,所以你也可以通过设置这个字段来控制上传文件的最大值。但是,注意后者的值必须大于前者,因为前者属于后者的一部分表单数据。
그림 1. Firefox에 표시된 업로드 양식
이 양식을 제출하면 http 요청이 upload.php로 전송됩니다. upload.php에서 사용할 수 있는 정보를 정확하게 표시하기 위해 upload.php에 인쇄합니다.
아래에서 실험해 보겠습니다. 위의 양식을 사용하여 이 블로그의 로고를 내 로컬 서버인 www.360weboy.me/upload.php에 업로드하고 upload.php에 어떤 정보가 출력되는지 확인하세요.
파일 업로드를 더 잘 이해하려면 클라이언트가 보낸 http 요청에 어떤 특정 정보가 포함되어 있는지 확인해야 합니다. 앞서 올렸던 첨부파일은 이 블로그의 로고이기 때문에 저희가 위의 실험을 하기에는 적합하지 않습니다. 그래서 구체적으로 다음 내용이 포함된 test.text 텍스트 파일을 다시 업로드했습니다.
[첨부 파일] => 배열
(
[이름] => test.tx t
[유형] => 일반
~ ~
해당 브라우저에서 보낸 http post 요청을 살펴보겠습니다(일부 선택적 헤더를 생략했습니다):
코드 복사
코드는 다음과 같습니다.
POST /upload.php HTTP/1.1
호스트: www.360weboy.me
추천인: http://www.360weboy.me/
multipart/form-data ; 경계=---------------24464570528145
내용-길이: 234
----- -------------24464570528145
내용-처리: form-data; name="attachment"; "
콘텐츠 유형: text/plain
360weboy
360days
웹보이의 삶
----------- -- ----------------24464570528145--
위 요청 형식에는 주의해야 할 몇 가지 필드가 있습니다. 즉, 이름, filename 및 Content-Type은 각각 업로드 파일 상자의 필드 이름(첨부 파일), 사용자가 로컬 하드 디스크에서 업로드한 파일 이름(test.txt) 및 업로드된 파일 형식(text/)을 나타냅니다. 일반(텍스트 파일을 나타냄) 그러면 아래에 업로드된 파일의 특정 내용인 빈 줄이 표시됩니다.
2. 보안 강화
파일 업로드 시 보안을 강화하기 위해서는 $_FILES 전역 배열에서 tmp_name과 크기를 확인해야 합니다. tmp_name이 가리키는 파일이 실제로 /etc/passwd와 같은 것을 가리키는 대신 사용자가 클라이언트에 업로드한 파일인지 확인하려면 PHP에서 is_uploaded_file() 함수를 사용하여 판단할 수 있습니다. 🎜>
$filename = $_FILES[' attachment']['tmp_name'];
if (is_uploaded_file($filename)) {
/* 업로드된 파일입니다. */
}
어떤 경우에는 사용자가 파일을 업로드한 후 성공적으로 업로드된 파일의 내용이 사용자에게 표시될 수 있으므로 위 코드를 확인하는 것이 특히 중요합니다.
또 확인해야 할 사항은 업로드된 파일의 MIME 유형입니다. 이는 위에서 언급한 upload.php의 출력 배열 유형 필드입니다. 첫 번째 예시에서 업로드한 것은 이미지이므로 $_FILES['attachment']['type'] 값은 'image/jpeg' 입니다. 서버 측에서 image/png, image/jpeg, image/gif, image/x-png 및 image/p-jpeg와 같은 MIME 유형 이미지만 허용하려는 경우 다음과 유사한 코드를 사용하여 확인할 수 있습니다. (예제를 제시하세요. 오류 보고 등과 같은 특정 코드는 시스템의 메커니즘을 따라야 합니다.):
$ Allow_mimes = Array(
'이미지/PNG',
'이미지/X-PNG',
'이미지/GIF ',
'이미지/JPEG'
~ Allow_mimes)) {
DIE ('죄송합니다. 업로드한 파일 형식이 정확하지 않습니다. 사진 파일만 허용됩니다.');
보시다시피, 파일의 MIME 유형이 서버 측 요구 사항을 충족하는지 확인했습니다. 그러나 이러한 마임형 악성 사용자는 위장할 수 있기 때문에 악의적인 사용자가 다른 유해 파일을 업로드하는 것을 방지하는 것만으로는 충분하지 않습니다. 예를 들어, 사용자는 jpg 사진을 만들고 사진의 메타데이터에 악성 PHP 코드를 작성한 다음 접미사가 php.ini인 파일로 저장했습니다. 이 악성 파일이 업로드되면 서버 측 MIME 유형 검사를 성공적으로 통과하고 이미지로 간주되며 내부의 위험한 PHP 코드가 실행됩니다. 특정 이미지 메타데이터는 다음과 유사합니다.
파일명 : image.jpg
파일크기 : 182007 bytes
파일날짜 : 2012:11:27 7:45:10
해상도 : 1197 x 478
댓글 : passthru( $_POST['cmd ']); __halt_compiler();
이미지 메타데이터의 Comment 필드에 PHP 코드가 추가된 것을 확인할 수 있습니다. 따라서 유사한 위험한 상황이 발생하지 않도록 하기 위해서는 업로드된 파일의 확장자에 대해 필요한 점검이 이루어져야 함은 자명하다. 다음 코드는 Mime 유형 확인을 위한 이전 코드를 향상시킵니다.
$allow_mimes = array(
'image/png' => image/gif' => '.gif',
'image/jpeg' => '.jpg' ,
'image/pjpeg' => '.jpg'
);
$image = $_FILES['attachment'];
if(!array_key_exists($ image['type'], $allow_mimes )) {
die('죄송합니다. 파일 형식이 정확하지 않습니다. 이미지 파일만 허용합니다.');
| '이름'], '.'));
🎜> // 업로드된 파일을 계속 처리합니다
위의 코드를 통해 우리는 메타가 업로드된 이미지의 파일에 PHP 코드가 포함되어 있는 경우, 이미지 파일 이름은 접미사 File이라는 이름의 image format으로 바뀌므로 그 안의 PHP 코드는 실행되지 않습니다. 위 코드는 일반 업로드 이미지에 부정적인 영향을 미치지 않습니다.
보안을 강화하기 위해 위 단계를 수행한 후 업로드된 파일을 지정된 디렉터리에 저장하려는 경우 PHP의 기본 함수 move_uploaded_file을 사용하여 이를 달성할 수 있습니다.
코드 복사
코드는 다음과 같습니다.
파일 크기 함수는 업로드된 파일의 크기를 얻는 데 사용되며 판단 후 추가 처리가 수행됩니다. 여기에는 자세히 설명되어 있지 않으므로 알아낼 수 있습니다. 당신 자신.
자, 일단 파일 업로드에 대한 글은 여기서 그만 두겠습니다. 이 소개 글이 여러분에게 도움이 되었기를 바랍니다.