2013-04-08 24 views
7

Tôi gặp sự cố đã tăng lên nhiều lần trên SO, nhưng dường như tôi không thể tìm ra giải pháp để khai thác! Tôi đang cố gắng để cung cấp một tập tin pdf cho khách hàng mà không có nó mở trong trình duyệt, tải tập tin nhưng nó bị hỏng khi tôi mở nó và thiếu một vài byte từ tập tin gốc. Tôi đã thử một số phương pháp như vậy để tải về các tập tin nhưng tôi sẽ chỉ cho bạn thấy mới nhất tôi đã sử dụng và hy vọng nhận được một số thông tin phản hồi.Force Tải xuống tệp PDF, tệp bị hỏng

Tôi cũng đã mở tệp PDF đã tải xuống trong trình chỉnh sửa văn bản và không có lỗi php nào ở trên cùng mà tôi có thể thấy! Tôi cũng biết rằng readfile() là nhanh hơn nhiều nhưng với mục đích thử nghiệm, tôi tuyệt vọng để có được bất cứ điều gì làm việc vì vậy tôi sử dụng phương pháp (! Feof()) trong khi!

Dù sao đủ lan man, heres mã (lấy từ why my downloaded file is alwayes damaged or corrupted?):

$file  = __DIR__ . '/reports/somepdf.pdf'; 
$basename = basename($file); 
$length = sprintf("%u", filesize($file)); 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="' . $basename . '"'); 
header('Content-Transfer-Encoding: binary'); 
header('Connection: Keep-Alive'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Pragma: public'); 
header('Content-Length: ' . $length); 

ob_clean(); 
set_time_limit(0); 
readfile($file); 

Cũng cần lưu ý là sự khác biệt về kích thước tập tin:

Original: 351,873 bytes 
Downloaded: 329,163 bytes 
+1

Bạn đã thử 'readfile() '? – barbashov

+0

@ DavidC799: Nếu bạn muốn thảo luận về câu trả lời của một câu hỏi trước, vui lòng để lại nhận xét ở đó. Không chỉ thả ở đây một số mã và nói với chúng tôi "nó không hoạt động". Hãy ghi nhớ, chỉ có ai đó khác chấp nhận câu trả lời đó, điều đó không có nghĩa là mã phải làm việc cho bạn. Và cho mục đích thử nghiệm, vui lòng giảm mã xuống mức tối thiểu để kích hoạt vấn đề. Ví dụ. không có chức năng, chỉ là một tên tệp được mã hóa cứng. Sử dụng readfile. – hakre

+0

@barbashov vâng tôi đã thử một số phương pháp khác nhau. – DavidC799

Trả lời

7

Hãy chắc chắn rằng bạn không chạy bất kỳ nén bộ xử lý đệm đầu ra, chẳng hạn như ob_gzhandler. Tôi đã có một trường hợp tương tự và tôi đã phải vô hiệu hóa bộ đệm đầu ra để làm việc này đúng cách

+0

Thực ra tôi là thế! Bây giờ bạn đề cập đến nó tôi đã nhìn thấy một người nào khác đề cập đến trong bài viết khác. Sẽ thử một vài điều và cho bạn biết nó như thế nào. Xin lỗi cho những rắc rối! – DavidC799

+0

Thành công! Rất cám ơn sự giúp đỡ của bạn, luôn luôn có điều gì đó đơn giản như vậy: ( – DavidC799

+0

@ DavidC799: Vâng, chỉ cần đọc các câu hỏi khác, hầu hết các câu trả lời trên trang web đã được bạn chỉ cần tìm chúng;) – hakre

6

Bạn đang sử dụng ob_gzhandler trên bộ đệm đầu ra.

Nó hoạt động theo khối lượng đầu ra gzencoding. Đầu ra sau đó là một luồng các khối được mã hóa.

Mỗi đoạn cần phải nhận một số byte để được mã hóa, do đó, đầu ra có một chút đệm cho đến khi có đủ byte.

Tuy nhiên, ở cuối tập lệnh, bạn loại bỏ bộ đệm còn lại thay vì xóa bộ đệm.

Sử dụng ob_end_flush() thay vì ob_clean() và tệp được hoàn toàn và không bị hỏng.

Bạn phải sử dụng mã hóa chuyển của ob_gzhandler khi tải lên tệp không gặp bất kỳ sự cố nào khi bạn không hủy bộ đệm đầu ra trước khi nó có thể thực hiện công việc.

Điều này cũng tương tự nếu bất kỳ bộ đệm đầu ra nào khác hoạt động chunked sẽ được kích hoạt là .

đang

Ví dụ:

$file  = __DIR__ . '/somepdf.pdf'; 
$basename = basename($file); 
$length = sprintf("%u", filesize($file)); 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="' . $basename . '"'); 
header('Content-Transfer-Encoding: binary'); 
header('Connection: Keep-Alive'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Pragma: public'); 
header('Content-Length: ' . $length); 

ob_end_flush(); // <--- instead of ob_clean() 

set_time_limit(0); 
readfile($file); 

return; 

(FYI: thực sự ngay cả những ob_end_flush(); là không cần thiết, một phần quan trọng không phải là để chỉ đá đầu ra-đệm trước khi nó có thể làm đó là công việc)

+0

Tôi có thể xác nhận rằng mã của hakre hoạt động như mong đợi; Cảm ơn bạn đã giải thích chi tiết – periklis

+0

Ngoài ra tôi đã chỉ cần kiểm tra readfile() nguồn trong PHP và bạn nên (nếu bạn có thể) luôn luôn sử dụng nó thay vì làm riêng của fopen/đệm đọc như trong câu hỏi. 'readfile()' vượt trội hơn nhiều đối với các đầu ra tải xuống tệp vì nó có thể sử dụng các lợi ích trong SAPI mà không thể có trong mã người dùng. – hakre

-1

tôi đã chiến đấu với việc sử dụng bố cục nội dung để thúc đẩy quá trình tải xuống PDF trong hai ngày trước khi tìm giải pháp cho vấn đề của tôi. Các tệp PDF của tôi cũng có kích thước nhỏ hơn và bị hỏng - tuy nhiên, tôi có thể mở chúng trong Windows Preview - không chỉ Adobe. Sau nhiều lần khắc phục sự cố, tôi phát hiện ra rằng Adobe dự kiến% PDF trong 1024 byte đầu tiên của tệp. Tôi đã làm tất cả kiểm tra loại tệp của tôi trong mã php của tôi trước khi tạo tiêu đề. Tôi đã lấy phần lớn mã trước tiêu đề và tệp PDF của tôi đã được sửa.

Bạn có thể không được cài đặt nó lên giống như cách tôi đã làm, nhưng nó có thể là cùng một vấn đề:

http://helpx.adobe.com/acrobat/kb/pdf-error-1015-11001-update.html