PHP сохраняет поврежденный файл

183
12 июля 2018, 07:30

Существует задача: сохранить файл по ссылке с помощью PHP и предоставить к нему доступ в Android приложении.

Ниже приведен код, который занимается сохранением файла.

function SaveFile($URL, $Path) {
    return copy($URL, $Path);
}

Предположим, необходимо сохранить музыкальный файл в формате MP3. Функция успешно сохраняет файл на сервер (расширение у файла на сервере отсутствует), однако, скачав и установив расширение файлу в OS Windows, он воспроизводится некорректно. Музыки не слышно, лишь какие-то странные звуки.

С изображением абсолютно так же - исходный файл практически не распознать.

К слову, тот же музыкальный файл успешно воспроизводится средствами MediaPlayer OS Android.

Почему так происходит? И как это можно исправить?

Альтернативная функция.

private function SaveFile($URL, $Path) {
    $ReadFile = fopen ($URL, "rb");
    if ($ReadFile) {
        $WriteFile = fopen ($Path, "wb");
        if ($WriteFile){
            while(!feof($ReadFile)) {
                fwrite($WriteFile, fread($ReadFile, 4096));
            }
            fclose($WriteFile);
        }
        fclose($ReadFile);
    }
}
Answer 1

Краткий ответ s/0x0d0x0a/0x0a/g.

Полный ответ. В винде есть такое понятие как открытие текстового файла и бинарного (в линуксе оно лишено смысла). Суть заключается в том, что если файл открыть как бинарный, то все в него пишется так, как ожидается, а если как текстовый, то символ перевода строки \n (0x0A) будет кодироваться как 0х0D 0x0A. А для картинок/музыки это почти всегда смертельно. Собственно, эта бага и описана в документации php на функцию fopen.

Что делать? Либо перевести сервер на линукс, либо у функций fopen (и им родственным) добавить к второму параметру букву b.

Answer 2

Как оказалось, PHP нужно расширение файла, чтобы корректно записать файл. Причина этого требования мне неясна, но, по-видимому, указание "?b" не гарантирует принудительное включение бинарного режима. Однако это лишь мое предположение - оно может быть ошибочным.

В общем, переменная $Path должна иметь расширение файла.

READ ALSO
Создание директории в Entity Symfony 4

Создание директории в Entity Symfony 4

Изучаю Symfony, пытаюсь структурировать файлы, есть следующий класс:

200
Авторизация в Instagram с помощью php?

Авторизация в Instagram с помощью php?

Есть сайт с авторизацией через ИнстаграмВ API инста добавил приложение и всё что для него нужно

166
Проверка текстового поля на ввод цифр

Проверка текстового поля на ввод цифр

Как проверить текстовое поле, получаемое через post на цифры, и вывести ошибку?

200