Файл, скопированный с URL-адреса, усекается

У меня проблема с копированием файла. Мой код:

$file = "https://www.ilportaleofferte.it/portaleOfferte/resources/opendata/csv/offerteML/2019_1/PO_Offerte_G_MLIBERO_20190130.xml";

$newfile = $_SERVER['DOCUMENT_ROOT'] . '/input/PO_Offerte_G_MLIBERO_20190130.xml';

if (copy($file, $newfile)) {
    echo "salvato<br>";
} else {
    echo "ERROR inport file PO_Offerte_".$data.".".$ext."<br>";
    die;
}

copy() выдает true, файл создается но некоторые строки в конце файла отсутствуют... файл 3.6мб и 0.3 в конце файла отсутствуют...

Если я загружаю файл вручную, все в порядке, поэтому источник завершен...

На самом деле у меня такая же проблема, если я получаю содержимое файла с помощью file_get_contents() и пытаюсь сохранить его в файле, используя функцию записи файла...

Я не думаю, что upload_max_filesize и post_max_size на самом деле участвуют в copy(), но они установлены на 20 МБ.

любой совет?

Благодарность

stackoverflow.com/questions/3938534/… ?
Quasimodo's clone 31.01.2019 04:19

привет, Квазимодо, я пробовал также с file_put_contents, но та же проблема

illinois 31.01.2019 11:58

Можем ли мы взглянуть на содержимое файла, который вы пытаетесь скопировать?

Parantap Parashar 07.02.2019 09:15

конечно... ну... размещенный URL-адрес является истинным URL-адресом

illinois 08.02.2019 13:54

Попробуйте скачать тот же файл из другого источника. т.е. загрузите файл в браузере, загрузите на свой сервер, используйте URL-адрес этого сервера. Таким образом, вы можете проверить, имеет ли исходный сервер какое-либо отношение к этому.

yunzen 12.02.2019 10:08

Соединение с этим сервером кажется немного нестабильным. Может у вас проблема с тайм-аутом?

yunzen 12.02.2019 10:11

У меня такие же выпуски, попробуйте сжать их классом ZipArchive перед загрузкой файла, чтобы избежать повреждения. php.net/manual/en/class.ziparchive.php

Pascal Tovohery 13.02.2019 13:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
7
481
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Взгляните на свой php.ini. Вероятно, вам придется увеличить эти два параметра

upload_max_filesize и post_max_size

Исходный файл представляет собой ресурс https://. Может быть, скорее ограничение памяти. Я не знаю, как работает copy (возможно, буферизует потоки).

Quasimodo's clone 31.01.2019 04:20

У вас проблема, потому что вы используете протокол HTTPS. Функции copy() и file_get_content() имеют некоторые проблемы с работой по HTTPS. Более надежный способ загрузить удаленный файл — использовать CURL. Например:

$url = 'https://www.ilportaleofferte.it/portaleOfferte/resources/opendata/csv/offerteML/2019_1/PO_Offerte_G_MLIBERO_20190130.xml';    
$filePath = $_SERVER['DOCUMENT_ROOT'] . '/input/PO_Offerte_G_MLIBERO_20190130.xml';

$ch = curl_init($url);
$fp = fopen($filePath, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);

Plea try this connection timeout function,Hope this thing will work for you.

$url=curl_init("https://www.ilportaleofferte.it/portaleOfferte/resources/opendata/csv/offerteML/2019_1/PO_Offerte_G_MLIBERO_20190130.xml"); 
$set_timeout=400; 
$newfile=$_SERVER['DOCUMENT_ROOT'] . '/input/PO_Offerte_G_MLIBERO_20190130.xml';
curl_setopt($url, CURLOPT_CONNECTTIMEOUT, $set_timeout); 
$content = curl_exec($url);//execute request
if ($content)
{
    $copied_file = fopen($newfile, "w"); 
    if (fwrite($copied_file , $content)){
        echo "Done successfully";
    }
    else{
        echo "unable to write file";
        fclose($copied_file ); 
    }
}
else {
    echo "Something Went wrong";
}

Привет, Аджай, спасибо, сначала ваш скрипт попал в «что-то пошло не так», я получаю журналы ошибок, и я понял, что это проблема с ssl, чем я установил curl_setopt ($session, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt ($ сессия, CURLOPT_SSL_VERIFYPEER, 0); .... файл копируется, но все еще вырезается... когда я анализирую xml с помощью simplexml_load_string(), он все равно не может создать объект из xml, потому что формат не соблюдается... тег отсутствует, потому что файл разрезанный

illinois 08.02.2019 11:15

Извините, тогда вам придется попробовать другое решение, и когда вы найдете какое-либо возможное решение, пожалуйста, загрузите его здесь.

Ajay Katariya 08.02.2019 12:21

http://php.net/manual/en/function.copy.php

Я вижу это: exec("xcopy $source $destination");

Попробуй это!

Это специфично для Windows, не решает проблему, не работает с URL-адресами и имеет множество проблем с безопасностью.

Zenexer 11.02.2019 10:18

Похоже на memory_limit. Попробуйте установить более высокое значение в начале вашего скрипта.

ini_set('memory_limit' '1024m')

Ответ принят как подходящий

Я смог использовать file_get_contentsи форсирование протокола HTTP/1.1:

$context = stream_context_create([
    'http' => [
      'protocol_version' => '1.1',
      'header' => 'Connection: Close'
    ],
]);
$content = file_get_contents('https://www.ilportaleofferte.it/portaleOfferte/resources/opendata/csv/offerteML/2019_1/PO_Offerte_G_MLIBERO_20190130.xml', false, $context);
file_put_contents('document.xml', $content);

Сказав это, я бы рекомендовал использовать CURL:

$ch = curl_init();
$curlopts = array();
$curlopts[CURLOPT_RETURNTRANSFER] = true;
$curlopts[CURLOPT_VERBOSE] = true;
$curlopts[CURLOPT_URL] = 'https://www.ilportaleofferte.it/portaleOfferte/resources/opendata/csv/offerteML/2019_1/PO_Offerte_G_MLIBERO_20190130.xml';
curl_setopt_array($ch, $curlopts);
$content = curl_exec($ch);
file_put_contents('document.xml', $content);
curl_close($ch);

Проблема с http 1.0

Это должно исправить это:

$sc = stream_context_create(['http' => ['protocol_version' => '1.1']]);

copy($file, $newfile, $sc);

Поскольку URL-адрес поддерживает SSL, как правило, дополнительная информация должна быть упакована и отправлена ​​​​с запросом - для функции copy есть аргумент context. context позволяет указать метод, протокол и многое другое для поддержки запроса.

$url='https://www.ilportaleofferte.it/portaleOfferte/resources/opendata/csv/offerteML/2019_1/PO_Offerte_G_MLIBERO_20190130.xml';

/* download a copy from: https://curl.haxx.se/ca/cacert.pem */
$cacert=__DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem';
/* define where files are to be stored */
$dir='c:/temp/downloads/';

Использование функции stream_context_create() для создания контекста для запроса и copy для фактического выполнения запроса.

$filepath=$dir . basename( $url );

$args = array(
    'http'  =>  array( 'method' => 'GET', 'protocol_version' => '1.1' ),
    'ssl'   =>  array( 'verify_peer' => true, 'verify_peer_name' => true, 'allow_self_signed' => false, 'cafile' => $cacert )
);
$ctxt = stream_context_create( $args );
$status = copy( $url, $filepath, $ctxt );

if ( $status && file_exists( $filepath ) ){
    printf( 
        'The file "%s" downloaded successfully. %sMb written to disk.',
        $filepath,
        round( filesize( $filepath ) / pow( 1024, 2 ),2 )
    );
}

Другой и, возможно, лучший вариант — curl:

function downloadfile( $url=false, $dir=false, $cacert=false ){
    if ( $url && $dir ){

        /* define the save path */
        $filepath = $dir . basename( $url );

        /* time how long the download takes */
        $start=time();

        /* open a file pointer for use by curl */
        $fp = fopen( $filepath, 'w+' );

        /* create the curl request - write file directly */
        $ch = curl_init( $url );
        curl_setopt($ch, CURLOPT_HEADER, 0 );
        curl_setopt($ch, CURLOPT_TIMEOUT, 10 );
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
        curl_setopt($ch, CURLOPT_BINARYTRANSFER, true );
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true );
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36' );
        if ( parse_url( $url, PHP_URL_SCHEME )=='https' ){
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true );
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2 );
            curl_setopt($ch, CURLOPT_CAINFO, $cacert );
        }
        curl_setopt($ch, CURLOPT_ENCODING, '' );
        curl_setopt($ch, CURLOPT_FILE, $fp );# write to file

        /* the response */
        $obj=(object)array(
            'response'  =>  curl_exec($ch),
            'info'      =>  (object)curl_getinfo($ch),
            'error'     =>  curl_error($ch),
            'filepath'  =>  $filepath
        );

        /* tidy up */
        curl_close($ch);
        fclose($fp);

        /* calculate time operation took */
        $obj->duration=round( time() - $start, 2 );

        return $obj;
    }
}



/* run the function */
$obj = downloadfile( $url, $dir, $cacert );

if ( $obj->info->http_code==200 ){
    printf( 
        'The file "%s" downloaded successfully in approximately %ss. %sMb written to disk.',
        $obj->filepath,
        $obj->duration,
        round( filesize( $obj->filepath ) / pow( 1024, 2 ),2 )
    );
} else {
    printf(
        'Error: A problem was encountered downloading %s. The response code is: %d and error message: "%s"',
        $url,
        $obj->info->http_code,
        $obj->error
    );
}

Вышеупомянутые два метода, а также ручная загрузка привели к файлу размером 3,19 МБ.

Другие вопросы по теме