https://cafe.naver.com/delmadang/2361
알아두면 쓸데없는 팁.
제목이 좀 그렇군요 ^^
오래전에 납품된 프로그램에서 ftp 를 사용해서 파일을 전송하는 부분이 있었습니다. 이번에 운영서버 쪽에 문제가 생겨서 중간에 서버가 한대 추가 되는데 얘는 ftp 서버 를 쓸수가 없는 상황이 되어서 이런저런 궁리를 해봤는데 여튼 일을 최소화 시켜야 하는터라...
클라이언트 <-> 웹서버 <-> FTP 서버
이렇게 해볼까 했습니다.
클라이언트 에서는 기존 ftp 는 http로 바꿔서 웹서버에 노출된 엔드 포인트 로 접근 하고 중간에 웹서버 에서는 php 로 ftp 서버에 접속해서 파일을 전송하고 그 결과를 다시 클라이언트로 줘버리는거죠.
웹서버도 구려서 사용하는 데몬들도 버전도 낮고 무엇보다도 여기에 투자할 시간이 요따만큼 밖에 안되서 또 날림공사를 해봤습니다.
일단 별건 없고 php 도 할줄 몰라서 날림입니다. 온전한 코드는 아니고 그냥 흐름 정도만...
get_file.php
<?php
header('Content-Type: text/html; charset=utf-8');
//파라미터 받아서 필요한 이것저것 해줌~
//비정상적인 접근 처리도 해야하고... 로깅이 필요하면 하구 권한체크가 필요하면 그것도 하고 어쩌고 저쩌고...
//다운로드 파일은 임시파일로 uniqid() 함수로 중복이 안생기도록 해봅니다.
$g_tmp_file="/mnt/ramdisk/dms_".uniqid();
//ftp 서버에 접속하고
$gftp = new SFTP('192.168.0.100', $g_username, $g_password');
//이런코드 저런코드
//파일을 가져옵니다. 역시 양쪽 서버간에 문자셋 때문에 문제가 생기면 iconv 로 ...
$st_ftp_get = $gftp->get($g_serverfile, $g_tmp_file, FTP_BINARY);
//헤더에 써줄 파일크기와 이름
$dn_filesize = filesize( $g_tmp_file );
$dn_filename = $g_ftp_filename;
if (file_exists( $g_tmp_file )) {
header("Content-Type:application/octet-stream");
header("Content-Disposition:attachment;filename=$dn_filename"); //다운로드될 파일이름 -원래 이름과 같을 필요는 없음
header("Content-Length:".$dn_filesize); //파일크기
header("Content-Transfer-Encoding:binary");
header("Cache-Control:cache,must-revalidate"); //캐싱안하는걸로 no-store 나 no-cache 로..
header("Pragma:no-cache");
header("Expires:0");
if(is_file($g_tmp_file)){
ob_clean(); //출력버퍼 초기황
flush(); //짝궁인가? 모르겟지만 일단 써봄.
readfile( $g_tmp_file ); //파일을 읽음..
//print "OK";
delete_tmp_file( $g_tmp_file ); 끝나면 임시파일 지움
} else {
print "ERROR-FILE NOT FOUND(tmp)";
delete_tmp_file( $g_tmp_file );
}
}
//혹시 모르니 한번 더 확인
if (file_exists( $g_tmp_file ))
{
unlink( $g_tmp_file);
}
중요한 부분은 header 설정 하는 부분이랑 ob_clean, flush, readfile 정도가 되겟습니다. ftp 작업부분은 사용하는 라이브러리로 적당하게 하면 되겟고 출력버퍼 지우고 파일을 읽어들이면 그냥 다운로드가 됩니다. 웹브라우저 에서도 파일 저장창이 뜨니깐 뭐 IdHTTP 같은거로도 다운로드가 바로 됩니다.
이제 델파이에서...
var
vFS: TStream;
begin
vFS:= TFileStream.Create('다운로드경로\파일명', fmCreate); //get_file.php 에서 설정된 파일명과 다르게 지정할수 있음
try
IdHTTP1.Get('url/get_file.php?filename=파일이름&기타파라미터&등등등', vFS); //파일이름등에 한글이 포함된다면 URLEncode로 미리 바꿔주야함
finally
vFS.Free;
end;
end;
요래 하면 파일을 잘 가져옵니다.
고전중의 고전 TDownloadURL 로도 사용가능하겟고요..
엔드 포인트 하나만 노출되니깐 웹브라우저 에서도 디렉토리 리스팅 등으로 다른 파일들 노출도 안될테고 뭐 이래저래 잘 하면 괜찮을것 같네요 중간에 웹서버 가 물리적으로 분리가 안되더라도 http서버 하나 띄워서 로컬에서 ftp 로 접속해도 되고... 물론 그것때문에 조금 비용이 더 소요가 되긴 하겟지만 다른 설정하냐고 시간 다 소비 하는것 보다는 나을것 같습니다.
어차피 사용량이 많은 서비스도 아니라서...
간단하게 php로 해봤는데 뭐 다른걸로도 충분히 가능하겟죠?
오래된 구닥다리 방법이긴 합니다만 거창하게 이것저것 필요없어 맘에 들긴 합니다. 다양한 방법으로 응용 하면 여러가지 상황에 쓸수 있을것 같아요
추가내용.
쭈쭈님이 대용량 파일도 바로 다운로드가 시작되는지 물어보셔서 얼마나 되야 대용량인지는 모르겟지만 조금 확인을 해봤습니다.
지금 사용하는 업체의 환경은 거의 대부분 문서 파일들이라서 개별 파일들의 용량이 얼마 안되거든요.
일단 1 G 짜리 하나 넣어놓고 해봤더니 안됩니다. 흠.. 그람 500M정도? 안됩니다. 그람 100M 정도 잘됩니다. 그럼 200M 짜리...안됩니다. 헐~
구글링을 좀 해보니 readfile 를 사용할 경우 php 에서 memory-limit 변수의 값에 영향이 있답니다. phpinfo() 함수로 확인해봤더니 128M 으로 적용되어져 있네요 이를 무제한 으로 설정하고 해봤더니 1G 가 넘는것도 잘 됩니다.
1. ini_set 함수로 memory-limit 변수값을 적당하게 늘리거나 무제한으로 변경한다.
ini_set('memory-limit', -1); //메모리 제한 품 - 256M 등으로 구체적으로 설정가능 - 현재 세션에만 적용됨(아마도...)
if(is_file($g_tmp_file)){
ob_clean(); //출력버퍼 초기황
flush(); //짝궁인가? 모르겟지만 일단 써봄.
readfile( $g_tmp_file ); //파일을 읽음..
//print "OK";
delete_tmp_file( $g_tmp_file ); 끝나면 임시파일 지움
} else {
print "ERROR-FILE NOT FOUND(tmp)";
delete_tmp_file( $g_tmp_file );
}
2. readfile 대신 fread 함수같은걸로 조금씩 잘라서 처리한다. 적당한 크기로 잘라서 보내면 큰 파일들도 적당히 잘 보냄
$buff_size = 1024 * 1024; //1M 설정 사용시에는 적당한 사이즈로 ...
if (is_file ($g_tmp_file)) {
$file_handle = fopen( $g_tmp_file , 'rb'); //파일을 읽기전용으로 열고
while (!feof($file_handle)) { //파일끝까지 돌고돌아
echo fread($file_handle, $chunksize); //정해진 사이즈만큼 읽어서 출력함
ob_flush(); //나는 php 버퍼초기화
flush(); //나는 서버버퍼를 비움 -- 뭐 잘 이해는 안가는데 요기서 웹서버가 브라우저에 전달이 된다고? 여튼 쌍으로 콤비임
}
fclose($file_handle); //다끝나면 닫아줌
}
3. 뜻하지 않은 오류를 확인할수는 있었지만 정작 질문에 대한것은 확실하게는 모르겟습니다.
바로 시작이 되는가? 흠 일단 지금의 상황에서는 php 에서 ftp 서버에서 파일을 찾아 가져오는 단계가 있어서 이처럼 다운로드 할 파일을 준비 하는 과정을 제외 하고 생각해보면... 저도 뭐 그냥 대충 문서 몇개 살펴보는게 다 인지라 잘 모르겟습니다.
1. 웹브라우저 에서 주소줄에 파일까지 지정하는거 ( 예: https://어쩌구저쩌구/다운로드될파일.zip )
2. 웹브라우저 에서 php 파일을 호출하고 php 내부에서 파일을 읽어서 뿌림
둘다 공통적으로 같은 상황이라고 한다면... 예를 들어 서버상태 나 네트워크 상태나 기타 등등..
1번은 바로 다운로드가 되거나 저장위치를 묻는 확인창이 뜹니다.
2번은 1번보다는 쬐끔 시간이 더 걸리긴 하지만 체감상 느낌이 크지는 않았습니다.
정확하게 설정이나 확인등을 해볼수가 없어서 모르겟습니다. ㅠㅠ 언급했던대로 php 내부적으로 다운로드 할 파일을 분비 하는 과정이나 기타 작업들 을 제외한다면 크게~ 차이는 없을것이다. 입니다.
그럼 요기까지... 추후 새로운 사실을 알게된다면.... 그때 다시..
'삽질' 카테고리의 다른 글
delphi / ip 문자열 <-> 숫자 (0) | 2025.01.21 |
---|---|
키움증권 해외파생 - OpenAPI(w) 자동로그인/계좌비번설정 자동화 (0) | 2024.02.26 |
delphi / TComboBox, TListBox onDrawItem (0) | 2023.08.15 |
NeuroTechonology FingerPrint SDK 13 이용기 (1) | 2023.06.01 |
delphi - cxGrid - row별 Column implement editior 설정. (0) | 2022.06.24 |