Статьи

Как открыть Zip файлы с помощью PHP

ThemeForest имеет приятную особенность; Это позволяет авторам загружать zip-файлы, содержащие скриншоты их тем. Затем скрипт извлекает эти файлы и отображает изображения соответственно. Хотя я сомневаюсь, что разработчики использовали PHP для выполнения этой задачи … это то, что мы собираемся использовать!


  • Создайте простую форму загрузки, которая позволяет пользователю выбрать ZIP-файл.
  • Убедитесь, что пользователь выбирает zip-файл, а затем сохраните его как уникальный файл.
  • Извлеките содержимое из zip-файла и сохраните его в определенной папке.
  • Удалите zip-файл и отобразите его содержимое.
Загрузить форму
  • Создайте новый файл и сохраните его как index.html в корне вашего решения.
  • Далее мы создадим простую форму. Вставьте следующее в.
1
2
3
4
<form enctype=»multipart/form-data» action=»» method=»post»>
    <input type=»file» name=»fupload» /><br />
    <input type=»submit» value=»Upload Zip File» />
</form>

Каждый раз, когда вы разрешаете пользователям загружать файлы, вы должны установить «enctype» тега формы равным «multipart / form-data» . Затем мы установим действие, равное той же странице, и метод, равный post.

Форма HTML

Чтобы все было как можно проще, у нас есть только файл ввода и кнопка отправки. Обратите внимание, что мы установили имя входного файла на «fupload». Мы скоро будем использовать это значение, чтобы определить, была ли страница отправлена ​​обратно.

В самом верху вашей страницы index.php перед объявлением типа документа вставьте следующее:

1
2
3
4
5
<?php
if(isset($_FILES[‘fupload’])) {
    $filename = $_FILES[‘fupload’][‘name’];
    $source = $_FILES[‘fupload’][‘tmp_name’];
    $type = $_FILES[‘fupload’][‘type’];

Давайте сделаем это шаг за шагом.

  • Если задан входной тег с именем «fupload», выполните следующий код, в противном случае ничего не делайте.
  • Теперь нам нужно создать несколько переменных. Нам нужно захватить имя загруженного файла, каталог, в котором файл временно хранится, и тип файла, который был выбран.

Давайте предположим, что пользователь выбирает файл с именем «myPics.zip».

  • $ _FILES [‘fupload’] [‘name’] = «myPics.zip»
  • $ _FILES [‘fupload’] [‘tmp_name’] = некоторый временный каталог на сервере.
  • $ _FILES [‘fupload’] [‘type’] = «application / zip». (Это значение может меняться в зависимости от того, из какого браузера был загружен файл.
Содержимое глобального массива FILES

Далее, давайте разберем имя файла на две части: имя и расширение.

1
2
$name = explode(‘.’, $filename);
$target = ‘extracted/’ .

Продолжая наш пример файла «myPics.zip» — $ name [0] будет равно «myPics». $ name [1] будет равно «zip».

Далее мы создаем новую переменную с именем «$ target». Это будет папка, в которую будет сохранен наш файл. Чтобы гарантировать, что другой пользователь с тем же именем «myPics» не перезаписывает свои файлы, мы должны сохранить эти файлы в уникальном месте. Для выполнения этой задачи мы реализуем функцию time (). Если мы добавим это значение к имени загруженного файла, мы можем быть уверены, что получим уникальное имя папки!

$ target = «extract / myPics-02151985 /»

Сразу после вашей переменной $ target вставьте следующее:

1
2
3
4
5
6
7
8
$accepted_types = array(‘application/zip’, ‘application/x-zip-compressed’, ‘multipart/x-zip’, ‘application/s-compressed’);
 
foreach($accepted_types as $mime_type) {
    if($mime_type == $type) {
        $okay = true;
        break;
    }
}
  • Мы начнем с создания массива с именем $ accept_types. Быстрый поиск в Google по «типам zip mime» принесет нам четыре значения: «application / zip», «application / x-zip-compress», «multipart / x-zip», «application / s-compress» . Каждый браузер имеет свой собственный способ регистрации типа файла. Мы должны обязательно проверить каждое значение в таких случаях.
  • Для этого мы проверяем, имеет ли какой-либо из элементов в нашем массиве то же значение, что и «$ _FILES [‘fupload’] [‘type’]». Если они это сделают, мы установим нашу удобную переменную $ okay в значение handy-dandy, равное «true», и можем выйти из выражения «for» и быть уверенными, что пользователь фактически выбрал zip-файл.

К сожалению, Safari и Chrome не регистрируют тип для zip-файлов. Это создает проблему для нас. После небольшого исследования я не смог найти простое решение — без использования расширения (PEAR). Вместо этого мы позаботимся о том, чтобы имя файла как минимум заканчивалось на «zip». Следует отметить, что это не на 100% безопасно. Что если пользователь загрузил файл другого типа, который оканчивался на «zip»? Не стесняйтесь предлагать рекомендации! 🙂

1
$okay = strtolower($name[1]) == ‘zip’ ?
  • Мы будем использовать троичный оператор, чтобы сохранить это утверждение до одной строки. Если расширение имени файла ($ name [1]) равно ‘zip’, мы установим для $ okay значение true. В противном случае оно будет равно «ложно».

Далее мы проверим, является ли $ okay ложным. Если это так, мы знаем, что файл «zip» не был выбран. В таких случаях мы скажем PHP умереть.

1
2
3
if(!$okay) {
  die(«Please choose a zip file, dummy!»);
}
1
2
3
4
5
6
7
8
mkdir($target);
$saved_file_location = $target .
     
if(move_uploaded_file($source, $saved_file_location)) {
  openZip($saved_file_location);
} else {
  die(«There was a problem. Sorry!»);
}
  • Сначала нам нужно создать каталог, на который мы ссылаемся с нашей переменной $ target. Это легко сделать с помощью функции «mkdir».
  • Далее, давайте попробуем переместить загруженный файл из временного каталога в наш каталог $ target. Если эта процедура была выполнена успешно, мы вызовем функцию «openZip».

Создайте новую страницу и сохраните ее как «functions.php». Теперь добавьте следующий код:

Загрузить форму
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<?php
 
function openZip($file_to_open) {
    global $target;
     
    $zip = new ZipArchive();
    $x = $zip->open($file_to_open);
    if($x === true) {
        $zip->extractTo($target);
        $zip->close();
         
        unlink($file_to_open);
    } else {
        die(«There was a problem. Please try again!»);
    }
}
?>

Эта функция будет принимать один параметр: $ file_to_open. Этот параметр будет содержать расположение zip-файла, который мы пытаемся извлечь!

  • Чтобы использовать класс ZipArchive (), вы должны сначала убедиться, что в вашем файле php.ini включен php_zip.dll. Просто найдите эту строку, а затем удалите точку с запятой.
    PHP.NET Zip info
  • В любом классе нам нужно создать новый экземпляр объекта. Затем мы вызовем метод open и передадим местоположение файла, который должен быть открыт. При успешном выполнении этот метод вернет true. Если это так, мы извлечем содержимое zip-файла в папку. Мы уже создали путь к этой папке, когда создали переменную $ target. ( Примечание. Чтобы получить доступ к этой переменной, вам нужно добавить «global» перед переменной. Это скажет PHP выйти за пределы текущей функции и искать переменную $ target. ).
  • Как только файлы будут извлечены, мы удалим zip-файл — так как он нам больше не нужен!

Помните — мы создали наш новый файл «functions.php», но мы должны включить его! Добавьте следующее в начало страницы index.php сразу после открывающего тега PHP.

1
require_once ‘functions.php’;
Выводя содержимое

То, что у нас пока, работает отлично! Но, просто чтобы дать вам обратную связь, давайте просканируем новый каталог и выведем на экран его содержимое. Вы должны удалить этот следующий блок кода из вашего проекта. Это только для тестирования. Если вы хотите сохранить его, отобразите информацию в теге body.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
    $scan = scandir($target . $name[0]);
     
    print ‘<ul>’;
    for ($i = 0; $i<count($scan); $i++) {
        if(strlen($scan[$i]) >= 3) {
            $check_for_html_doc = strpos($scan[$i], ‘html’);
            $check_for_php = strpos($scan[$i], ‘php’);
             
            if($check_for_html_doc === false && $check_for_php === false) {
                echo ‘<li>’ .
            } else {
                echo ‘<li><a href=»‘ . $target . $name[0] . ‘/’ . $scan[$i] . ‘»>’ .
            }
        }
    }
    print ‘</ul>’;
}

Я не буду слишком подробно останавливаться на этой последней части — так как в этом нет необходимости. Однако, если вы хотите получить полное объяснение, обязательно посмотрите соответствующий скринкаст! Чтобы быстро подвести итог, этот последний скрипт сканирует наш новый каталог и выводит неупорядоченный список, содержащий содержимое.

Не слишком сложно, а? Это удобная функция, которая может быть легко внедрена в ваши проекты. Что вы думаете о безопасности, когда дело доходит до загрузки ZIP-файлов? Как мы можем быть уверены, что содержимое zip-файла не представляет опасности? Я хотел бы услышать мнение всех об этих последствиях для безопасности. При неправильном обращении хакер может нанести серьезный вред вашему серверу. Давайте обсудим это! Можно искать опасные типы файлов (файлы .htaccess) и удалять их.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?php
 
    include ‘functions.php’;
 
if(isset($_FILES[‘fupload’])) {
    $filename = $_FILES[‘fupload’][‘name’];
    $source = $_FILES[‘fupload’][‘tmp_name’];
    $type = $_FILES[‘fupload’][‘type’];
     
    $name = explode(‘.’, $filename);
    $target = ‘extracted/’ .
     
    // Ensures that the correct file was chosen
    $accepted_types = array(‘application/zip’,
                                ‘application/x-zip-compressed’,
                                ‘multipart/x-zip’,
                                ‘application/s-compressed’);
 
    foreach($accepted_types as $mime_type) {
        if($mime_type == $type) {
            $okay = true;
            break;
        }
    }
       
  //Safari and Chrome don’t register zip mime types.
    $okay = strtolower($name[1]) == ‘zip’ ?
 
    if(!$okay) {
          die(«Please choose a zip file, dummy!»);
    }
     
    mkdir($target);
    $saved_file_location = $target .
     
    if(move_uploaded_file($source, $saved_file_location)) {
        openZip($saved_file_location);
    } else {
        die(«There was a problem. Sorry!»);
    }
     
// This last part is for example only.
    $scan = scandir($target . $name[0]);
     
    print ‘<ul>’;
    for ($i = 0; $i<count($scan); $i++) {
        if(strlen($scan[$i]) >= 3) {
            $check_for_html_doc = strpos($scan[$i], ‘html’);
            $check_for_php = strpos($scan[$i], ‘php’);
             
            if($check_for_html_doc === false && $check_for_php === false) {
                echo ‘<li>’ .
            } else {
                echo ‘<li><a href=»‘ . $target . $name[0] . ‘/’ . $scan[$i] . ‘»>’ .
            }
        }
    }
    print ‘</ul>’;
}
 
?>
 
 
 
<!DOCTYPE html PUBLIC «-//W3C//DTD XHTML 1.0 Strict//EN» «http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd»>
  
<html>
  <head>
    <title>How to Upload and Open Zip Files With PHP</title>
    <meta http-equiv=»Content-Type» content=»text/html; charset=UTF-8″>
  </head>
  <body>
    <div id=»container»>
    <h1>Upload A Zip File</h1>
    <form enctype=»multipart/form-data» action=»» method=»post»>
        <input type=»file» name=»fupload» /><br />
        <input type=»submit» value=»Upload Zip File» />
    </form>
 
    </div><!—end container—>
  </body>
</html>