2009-05-20 27 views
5

Ứng dụng web PHP của tôi có API có thể nhận các tệp lớn hợp lý (tối đa 32 MB) được mã hóa base64. Mục tiêu là viết các tệp này ở đâu đó trên hệ thống tệp của tôi. Đã giải mã tất nhiên. Điều gì sẽ là cách ít tốn kém nhất để làm điều này?Cách giải mã64 các tệp lớn trong PHP

Chỉnh sửa: Nhận tệp qua API có nghĩa là tôi có chuỗi 32MB trong ứng dụng PHP, không phải tệp nguồn 32 MB ở đâu đó trên đĩa. Tôi cần phải giải mã chuỗi đó vào hệ thống tập tin.

Sử dụng base64_decode() của PHP không cắt vì nó sử dụng bộ nhớ vì vậy tôi tiếp tục chạy vào giới hạn bộ nhớ của PHP (Tôi biết, tôi có thể tăng giới hạn đó nhưng tôi không cảm thấy tốt về việc cho phép PHP để sử dụng 256MB hoặc hơn cho mỗi quá trình).

Bất kỳ tùy chọn nào khác? Tôi có thể làm điều đó bằng tay? Hoặc ghi tập tin vào đĩa được mã hóa và gọi một số lệnh bên ngoài? Bất cứ suy nghĩ nào?

Trả lời

20

Mặc dù đây đã là một câu trả lời được chấp nhận, tôi có một đề nghị khác nhau.

Nếu bạn đang lấy dữ liệu từ API, bạn không nên lưu toàn bộ tải trọng trong một biến. Sử dụng curl hoặc các trình tìm nạp HTTP khác, bạn có thể tự động lưu trữ dữ liệu của mình trong một tệp.

Giả sử bạn đang lấy dữ liệu thông qua một url GET đơn giản:

$url = 'http://www.example.com/myfile.base64'; 
$target = 'localfile.data'; 

$rhandle = fopen($url,'r'); 
stream_filter_append($rhandle, 'convert.base64-decode'); 

$whandle = fopen($target,'w'); 

stream_copy_to_stream($rhandle,$whandle); 
fclose($rhandle); 
fclose($whandle); 

Lợi ích:

  • nên được nhanh hơn (ít sao chép các biến lớn)
  • Rất ít bộ nhớ overhead

Nếu bạn phải lấy dữ liệu từ biến tạm thời, tôi có thể đề xuất Cách tiếp cận này:

$data = 'your base64 data'; 
$target = 'localfile.data'; 

$whandle = fopen($target,'w'); 
stream_filter_append($whandle, 'convert.base64-decode',STREAM_FILTER_WRITE); 

fwrite($whandle,$data); 

fclose($whandle); 
+0

Một ý tưởng hay, nhưng không phải là những gì tôi đang tìm kiếm. Trong trường hợp của tôi, các ứng dụng máy khách đang đẩy các tệp lớn lên XML-RPC (HTTP POST) tới máy chủ của tôi (cùng với một vài tham số khác). Khách hàng có thể đứng sau NAT và tường lửa, do đó, tìm nạp dữ liệu từ máy khách bằng cách sử dụng GET là không thể. –

+0

Nếu cấu trúc của phản hồi rpc xml hơi tĩnh, bạn có thể di chuyển qua cơ thể phản hồi theo cách thủ công, vì vậy bạn vẫn có thể tránh hoàn toàn việc sử dụng bộ nhớ. Nếu bạn phải đặt dữ liệu trong một biến tạm thời, bạn có thể thay đổi thiết lập một chút. (Tôi đang cập nhật ví dụ ngay sau ví dụ;)) – Evert

+0

Cảm ơn bạn đã cập nhật. Tôi thấy nó vượt trội so với câu trả lời mà tôi đã chấp nhận ban đầu. –

11

Giải mã dữ liệu theo các đoạn nhỏ hơn. Bốn ký tự của dữ liệu Base64 bằng ba byte dữ liệu “Base256”.

Vì vậy, bạn có thể nhóm mỗi 1.024 ký tự và giải mã chúng để 768 octet dữ liệu nhị phân:

$chunkSize = 1024; 
$src = fopen('base64.data', 'rb'); 
$dst = fopen('binary.data', 'wb'); 
while (!feof($src)) { 
    fwrite($dst, base64_decode(fread($src, $chunkSize))); 
} 
fclose($dst); 
fclose($src); 
+0

Cảm ơn. Một điều trước khi tôi đánh dấu điều này là được chấp nhận: Trong câu hỏi ban đầu của tôi, tôi đề cập đến tệp nguồn đi qua API. Vì vậy, nó là một biến (một chuỗi 32 MB) trong PHP và không phải là một tập tin bạn đọc từ. Có cái gì tôi có thể sử dụng thay vì fread của bạn() mà trả về cho tôi khối của một chuỗi hiệu quả? I E. mà không tạo ra quá nhiều bản sao trùng lặp mà gobble lên bộ nhớ? –

+0

Bạn có thể đọc từ đầu vào thông qua 'php: // input'. Xem http://docs.php.net/manual/en/wrappers.php.php – Gumbo

Các vấn đề liên quan