@@ -2561,6 +2561,166 @@ public function testXMLDecoder()
2561
2561
$ multi_curl ->start ();
2562
2562
}
2563
2563
2564
+ public function testDownload ()
2565
+ {
2566
+ // Create and upload a file.
2567
+ $ upload_file_path = \Helper \get_png ();
2568
+ $ uploaded_file_path = \Helper \upload_file_to_server ($ upload_file_path );
2569
+
2570
+ // Download the file.
2571
+ $ downloaded_file_path = tempnam ('/tmp ' , 'php-curl-class. ' );
2572
+ $ multi_curl = new MultiCurl ();
2573
+ $ multi_curl ->setHeader ('X-DEBUG-TEST ' , 'download_response ' );
2574
+ $ multi_curl ->addDownload (Test::TEST_URL . '? ' . http_build_query (array (
2575
+ 'file_path ' => $ uploaded_file_path ,
2576
+ )), $ downloaded_file_path );
2577
+ $ multi_curl ->complete (function ($ instance ) use ($ upload_file_path ) {
2578
+ \PHPUnit \Framework \Assert::assertFalse ($ instance ->error );
2579
+ \PHPUnit \Framework \Assert::assertEquals (md5_file ($ upload_file_path ), $ instance ->responseHeaders ['ETag ' ]);
2580
+ });
2581
+ $ multi_curl ->start ();
2582
+ $ this ->assertNotEquals ($ uploaded_file_path , $ downloaded_file_path );
2583
+
2584
+ $ this ->assertEquals (filesize ($ upload_file_path ), filesize ($ downloaded_file_path ));
2585
+ $ this ->assertEquals (md5_file ($ upload_file_path ), md5_file ($ downloaded_file_path ));
2586
+
2587
+ // Remove server file.
2588
+ \Helper \remove_file_from_server ($ uploaded_file_path );
2589
+
2590
+ unlink ($ upload_file_path );
2591
+ unlink ($ downloaded_file_path );
2592
+ $ this ->assertFalse (file_exists ($ upload_file_path ));
2593
+ $ this ->assertFalse (file_exists ($ downloaded_file_path ));
2594
+ }
2595
+
2596
+ public function testDownloadRange ()
2597
+ {
2598
+ // Create and upload a file.
2599
+ $ filename = \Helper \get_png ();
2600
+ $ uploaded_file_path = \Helper \upload_file_to_server ($ filename );
2601
+
2602
+ $ filesize = filesize ($ filename );
2603
+
2604
+ foreach (array (
2605
+ false ,
2606
+ 0 ,
2607
+ 1 ,
2608
+ 2 ,
2609
+ 3 ,
2610
+ 5 ,
2611
+ 10 ,
2612
+ 25 ,
2613
+ 50 ,
2614
+ $ filesize - 3 ,
2615
+ $ filesize - 2 ,
2616
+ $ filesize - 1 ,
2617
+
2618
+ // A partial temporary file having the exact same file size as the complete source file should only
2619
+ // occur under certain circumstances (almost never). When the download successfully completed, the
2620
+ // temporary file should have been moved to the download destination save path. However, it is possible
2621
+ // that a larger file download was interrupted after which the source file was updated and now has the
2622
+ // exact same file size as the partial temporary. When resuming the download, the range is now
2623
+ // unsatisfiable as the first byte position exceeds the available range. The entire file should be
2624
+ // downloaded again.
2625
+ $ filesize - 0 ,
2626
+
2627
+ // A partial temporary file having a larger file size than the complete source file should only occur
2628
+ // under certain circumstances. This is possible when a download was interrupted after which the source
2629
+ // file was updated with a smaller file. When resuming the download, the range is now unsatisfiable as
2630
+ // the first byte position exceeds the the available range. The entire file should be downloaded again.
2631
+ $ filesize + 1 ,
2632
+ $ filesize + 2 ,
2633
+ $ filesize + 3 ,
2634
+
2635
+ ) as $ length ) {
2636
+ $ source = Test::TEST_URL ;
2637
+ $ destination = \Helper \get_tmp_file_path ();
2638
+
2639
+ // Start with no file.
2640
+ if ($ length === false ) {
2641
+ $ this ->assertFalse (file_exists ($ destination ));
2642
+
2643
+ // Start with $length bytes of file.
2644
+ } else {
2645
+ // Simulate resuming partially downloaded temporary file.
2646
+ $ partial_filename = $ destination . '.pccdownload ' ;
2647
+
2648
+ if ($ length === 0 ) {
2649
+ $ partial_content = '' ;
2650
+ } else {
2651
+ $ file = fopen ($ filename , 'rb ' );
2652
+ $ partial_content = fread ($ file , $ length );
2653
+ fclose ($ file );
2654
+ }
2655
+
2656
+ // Partial content size should be $length bytes large for testing resume download behavior.
2657
+ if ($ length <= $ filesize ) {
2658
+ $ this ->assertEquals ($ length , strlen ($ partial_content ));
2659
+
2660
+ // Partial content should not be larger than the original file size.
2661
+ } else {
2662
+ $ this ->assertEquals ($ filesize , strlen ($ partial_content ));
2663
+ }
2664
+
2665
+ file_put_contents ($ partial_filename , $ partial_content );
2666
+ $ this ->assertEquals (strlen ($ partial_content ), strlen (file_get_contents ($ partial_filename )));
2667
+ }
2668
+
2669
+ // Download (the remaining bytes of) the file.
2670
+ $ multi_curl = new MultiCurl ();
2671
+ $ multi_curl ->setHeader ('X-DEBUG-TEST ' , 'download_file_range ' );
2672
+ $ multi_curl ->addDownload ($ source . '? ' . http_build_query (array (
2673
+ 'file_path ' => $ uploaded_file_path ,
2674
+ )), $ destination );
2675
+
2676
+ clearstatcache ();
2677
+
2678
+ $ instance_error = false ;
2679
+ $ multi_curl ->complete (function ($ instance ) use ($ filesize , $ length , $ destination , &$ instance_error ) {
2680
+ $ expected_bytes_downloaded = $ filesize - min ($ length , $ filesize );
2681
+ $ bytes_downloaded = $ instance ->responseHeaders ['content-length ' ];
2682
+ if ($ length === false || $ length === 0 ) {
2683
+ $ expected_http_status_code = 200 ; // 200 OK
2684
+ \PHPUnit \Framework \Assert::assertEquals ($ expected_bytes_downloaded , $ bytes_downloaded );
2685
+ } elseif ($ length >= $ filesize ) {
2686
+ $ expected_http_status_code = 416 ; // 416 Requested Range Not Satisfiable
2687
+ } else {
2688
+ $ expected_http_status_code = 206 ; // 206 Partial Content
2689
+ \PHPUnit \Framework \Assert::assertEquals ($ expected_bytes_downloaded , $ bytes_downloaded );
2690
+ }
2691
+ \PHPUnit \Framework \Assert::assertEquals ($ expected_http_status_code , $ instance ->httpStatusCode );
2692
+ $ instance_error = $ instance ->error ;
2693
+ });
2694
+ $ multi_curl ->start ();
2695
+
2696
+ if (!$ instance_error ) {
2697
+ $ this ->assertEquals ($ filesize , filesize ($ destination ));
2698
+ unlink ($ destination );
2699
+ $ this ->assertFalse (file_exists ($ destination ));
2700
+ }
2701
+ }
2702
+
2703
+ // Remove server file.
2704
+ \Helper \remove_file_from_server ($ uploaded_file_path );
2705
+
2706
+ unlink ($ filename );
2707
+ $ this ->assertFalse (file_exists ($ filename ));
2708
+ }
2709
+
2710
+ public function testDownloadErrorDeleteTemporaryFile ()
2711
+ {
2712
+ $ destination = \Helper \get_tmp_file_path ();
2713
+
2714
+ $ multi_curl = new MultiCurl ();
2715
+ $ multi_curl ->setHeader ('X-DEBUG-TEST ' , '404 ' );
2716
+ $ multi_curl ->addDownload (Test::TEST_URL , $ destination );
2717
+ $ multi_curl ->complete (function ($ instance ) use ($ destination ) {
2718
+ \PHPUnit \Framework \Assert::assertFalse (file_exists ($ instance ->getDownloadFileName ()));
2719
+ \PHPUnit \Framework \Assert::assertFalse (file_exists ($ destination ));
2720
+ });
2721
+ $ multi_curl ->start ();
2722
+ }
2723
+
2564
2724
public function testDownloadCallback ()
2565
2725
{
2566
2726
// Upload a file.
0 commit comments