최근에 요구 사항을 만들고 있습니다. 다른 시스템의 FTP 디렉토리에서 이미지 URL을 저장하는 파일을 다운로드 한 다음 파일의 URL 주소를 읽고 주소에 따라 이미지를 다운로드하여 하루에 패키지로 압축합니다. 평균적으로 하나의 주소 파일에는 약 4,000 개의 주소가 포함되어 있습니다. 즉, 파일을 스캔 한 후 약 4,000 장의 사진을 다운로드 한 다음 압축해야합니다. 다음은 내 구현 방법 및 최적화 프로세스를 기록합니다. 더 나은 방법이 있으면 공유 할 수 있습니다.
사용 된 프레임 워크 : SpringMVC
시간이 지정된 작업 구현 : org.springframework.scheduling.quartz.quartzjobbean;
FTP 환경 구성에 대해서는 이야기하지 않을 것입니다. 가상 머신에서 CentOS가 구축 한 FTP 서비스를 사용하여 FTP 계정 및 해당 디렉토리를 작성하고 미리 다운로드 해야하는 이미지 주소 파일을 업로드한다는 다른 블로그에서 녹음했습니다. 파일 콘텐츠 형식 "이미지 ID || 이미지 주소".
메소드 1. 구현하는 가장 쉬운 방법은 먼저 그림의 URL 주소를 저장하는 파일을 다운로드 한 다음 파일 트래버스를 읽고 다운로드 된 그림 메소드를 조정하여 그림을 로컬로 저장하고 다운로드 된 그림을 압축하는 것입니다. 완료 후 다운로드 된 사진을 삭제하고 압축 패키지 만 유지하십시오.
공개 클래스 PicteRetransferjob 확장 QuartzJobbean {Protected void executeInternal (jobExecutionContext Arg0)은 jobExecutionException {// 실제 ftp 구성은 구성 파일을 읽음으로써 얻어집니다. // ftp 주소 문자열 hostName = "192.168.1112"; // ftp port int port = 2001; /ftp 계정 문자열 username = "test1"; // ftp password string password = "test1"; // ftp 파일 스토리지 디렉토리 문자열 ftpdowload = "/"; // 파일 문자열의 로컬 스토리지 경로 = this.getClass (). getResource ( "/"). getPath (); // 이미지 주소 파일 스토리지 디렉토리 문자열 addrpath = Path.SubString (1, path.indexof ( "web-inf/classe")+"picaddr"; // 실제 다운로드 된 이미지 저장 디렉토리 문자열 picpath = path.SubString (1, path.indexof ( "web-inf/classe"))+"pic"; addrpath = addrpath.replace ( "%20", ""); picpath = picpath.replace ( "%20", ""); {// 파일 CreatFile (addrpath)을 만듭니다. // 파일 생성 creatfile (picpath); 문자열 oldaddrpath = addrpath; 문자열 oldpicpath = picpath; // ftp 연결 생성 ftputil2 ftputil2 = new ftputil2 (호스트 이름, 포트, 사용자 이름, 암호, ftpdowload, true); // ftp directory string [] files = ftputil2.listallfiles ()에서 파일을 전송합니다. // 로컬 데이터베이스에는 다운로드 된 파일의 테이블 레코드가 있습니다. 여기서는 데이터베이스와 FTP에 나열된 파일 이름을 쿼리합니다. 다운로드 된 파일이 다운로드되지 않고 반복 된 다운로드를 피하십시오. // 비교 프로세스는 아래에서 생략하고 파일 배열을 루프하고 로컬로 파일을 만듭니다 (int i = 0; i <files.length; i ++) {creatfile (addrpath+file.separator+filename); // ftpDowload는 파일을 저장하기위한 FTP 서버의 주소이며, AddRPath는 로컬 저장 파일의 주소입니다. // 파일이 성공적으로 다운로드되었는지 여부를 결정하는 반환 상태가 있습니다. // 파일을 성공적으로 다운로드 한 후 파일을 읽는 메소드이며 다운로드 할 이미지 주소는 컨테이너 부울 EntityState = setPicturedEtail (addrpath, picpath, filenameDate)에 저장됩니다. }} catch (예외 e) {e.printstacktrace (); // 파일 오류를 다운로드하는 문자 메시지를 보내기 위해 오류 로그를 기록하는 비즈니스 클래스를 클릭하십시오}} // 여기에서 이미지 주소를 읽기 시작 개인 부울 setPicturedEtail (String addrPath, String Picpath, String Syndate) { System.out.println("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- String row; int count = 0. // 각 행에 읽은 맵 <string, addrmap <string, while (row = br.readline ()) {count ++; addrmap.put [0], column [1]. System.out.println (새 날짜 ()); System.out.println("-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- e.printstacktrace ()}}}}}* URL 주소에 따라 사진을 다운로드하십시오 filename picaddr = null; URLConnection은 InputStream을 통해 바이트 배열에 직접 작성되며, 불완전한 다운로드 이미지를 사용하여 org.apache.commons.ioutils.tobytearray ()를 사용합니다 BYTES // 스트림의 데이터는 BYTE 배열로 읽히고, 스트림의 데이터는 새 파일을 지 웁니다. fos.close (); zippic (picpath, syncdate, addrmap); {// 압축 해야하는 파일 목록에서 ziputil.zipbystream (piclist (picpath+syndate+). zip "); if (! file.exists ()) {file.mkdirs (); 방법 2 : 멀티 스레드 다운로드, 스트림의 직접 압축
방법 1 기본 기능이 구현되지만 다운로드해야 할 사진이 너무 많고 로컬 이미지 파일을 압축하고 사진 삭제도 시간이 많이 걸리므로 속도를 최적화 할 수있는 두 곳이 있습니다. 하나는 사진 다운로드의 효율성을 향상시키고 다른 하나는 압축 효율을 향상시키는 것입니다.
다운로드 효율을 향상시키는 방법은 멀티 스레드 다운로드를 사용할 수 있으며 압축 효율을 향상시키는 방법은 이미지를 로컬로 저장하지 않고 파일 스트림을 직접 압축 할 수 있습니다.
멀티 스레딩 구현 방법 : 먼저 다운로드 해야하는 파일의 주소 목록을 저장합니다. 멀티 스레딩을 사용하여 다운로드하려면 다른 스레드로 다운로드 한 사진이 반복되지 않도록해야합니다. 따라서 깃발을 구별하려면 깃발이 필요합니다. 현재 인덱스 카운터를 사용하여 각 스레드에서 다운로드 한 일정량의 사진에 따라 나눌 수 있습니다. 400 개의 이미지마다 0에서 시작하여 하나의 스레드를 사용하여 매번 다운로드 할 수 있으므로 필요한 스레드 수를 결정할 수 있으며 각 스레드에서 다운로드 한 사진은 반복되지 않습니다.
압축 파일의 구현 방법 : 압축 파일을 생성하는 필수의 본질은 압축 해야하는 파일 스트림을 읽은 다음 압축 패키지를 생성하는 것이기 때문에 컨테이너를 사용하여 다운로드 된 이미지 파일을 작성하는 대신 모든 스레드가 다운로드 한 이미지 스트림 데이터를 저장 한 다음 스트림 데이터를 압축 도구 클래스에 직접 압축 할 수 있습니다. 이렇게하면 이미지 파일을 읽는 지루한 과정을 생략하여 스트림을 생성 한 다음 압축 패키지를 생성 한 다음 로컬 이미지 파일을 삭제합니다.
변환의 주요 구현은 다음과 같습니다.
/ *** 하루별로 다운로드 된 사진을 압축* @throws ioexception*/ private boolean zippic (String picpath, String Syndate, Map <String, String, string)은 ioexception을 던지기 {// 다중 스레드 스토리지 이미지 스트림이기 때문에 스레드 안전 맵이 필요하므로 ConcurenthShmap 맵 <incutstream> ConsurenThashMap <String, inputStream> (); // 각 스레드에서 다운로드 한 사진 수는 여기에서 정의되어 int count = 400; // 다운로드 해야하는 이미지 주소 저장 목록 <enty <string, string >> addrlist = new ArrayList <Entry <String, String >> (addrmap.entryset ()); // 스레드 수는 스레드 수를 추가하여 마지막 400 미만의 이미지를 다운로드 할 스레드를 만들려면 int nthreads = (addrlist.size ()/count) +1; // countdownLatch countdownlatch = new CountdownLatch (nthreads); {boolean downpic = false; // multithread 다운로드 사진을 실행하여 downpic = downpic (picpath, addrlist, piclist, picturelist, nthreads, count); if (downpic) {ziputil.zipbyArray (piclist, 새 파일 (picpath+syncate+". zip")); } true를 반환합니다. } catch (예외 e) {e.printstacktrace (); 거짓을 반환합니다. }}다음은 스레드 풀의 생성입니다
/ *** URL 주소에 따라 그림을 다운로드* @Throws InterruptedException*/ private boolean downpic (문자열 picpath, list <enthring <string, string >> addrlist, map <string, byte []> piclist, map <string, inputStream> picturelist, int nthreads, int count) {excurection {interruptedExcly ThreadPool = Executor.NewFixedThreadPool (nthreads); // 두 카운터 생성 COUNTDOWNLATCH 시작 = New CountdownLatch (0); CountdownLatch End = New CountdownLatch (Nthreads); // 루프 (int i = 0; i <nthreads; i ++) {list <eptry <string, string >> subaddrlist = null; // 각 스레드에서 실행되는 데이터를 계산하면 ((i + 1) == nthreads) {int startIndex = (i * count); int endindex = addrlist.size (); 서브 아인드리스트 = addrlist.sublist (startIndex, endindex); } else {int startIndex = (i * count); int endindex = (i + 1) * count; 서브 아인드리스트 = addrlist.sublist (startIndex, endindex); } // 스레드 클래스 picdownload myhead = new picdownload (picpath, subaddrlist, piclist, picturelist); // 여기에서 스레드를 실행하는 방법은 스레드 풀에서 threadPool.Execute (myhead) 메소드를 호출하는 것입니다. try {ThreadPool.Execute (myhead); } catch (예외 e) {// 레코드 오류 로그를 반환합니다. }} begin.countdown (); end.await (); // 스레드 풀을 닫습니다. threadpool.shutdown (); // 여기에서 스레드 풀의 모든 스레드가 내려 가기 전에 종료 될 때까지 루프해야합니다. 테스트 중이 단계로 인해 자식 스레드는 이미지를 다운로드했지만 완료되지 않았으며 메인 스레드가 다운되어 압축 패키지의 사진이 없습니다. // COUNTDOWNLATCH를 사용하여/*를 구현하여 (true) {if (strook.isterminated ()) {system.out.println ( "모든 자식 스레드가 끝났습니다!"); 부서지다; }}*/ return true; }다음은 스레드 구현입니다
클래스 Picdownload emplements runnable {// 그림 목록 목록 <entry <string, String >> addrlist; // 그림 목록을 성공적으로 다운로드 한지도 <string, byte []> piclist; Map <String, InputStream> picturelist; // 그림의 로컬 저장 경로 문자열 picpath; CountdownLatch 시작, 끝; public picdownload (문자열 picpath, list <eptry <string, string >> addrlist, map <string, inputstream> piclist, countdownlatch 시작, countdownlatch 끝) {this.addrlist = addrlist; this.piclist = piclist; this.picpath = picpath; this.begin = 시작; this.end = 끝; } @override public void run () {try {system.out.println (thread.currentThread (). getName ()+"------"+thread.currentThread (). getId ()); 다운 포스처 (addrlist); //system.out.println (countdownlatch.getCount ()); begin.await (); } catch (예외 e) {e.printstacktrace (); } 마침내 {end.countdown (); //countdownlatch.countdown (); }} public boolean downpicture (list <eptry <string, string >> addrlist) 예외 {inputstream is = null; fileoutputStream fos = null; url url = null; 문자열 filename = null; 문자열 picaddr = null; 파일 pic = null; try {for (map.entry <string, string> addrentry : addrlist) {filename = addrentry.getKey (); picaddr = addrentry.getValue (); // URL 객체 생성 URL = new URL (picaddr); is = url.openstream (); // URLConnection에 의해 얻은 스트림은 InputStream을 통해 바이트 배열로 직접 기록되며 데이터가 손실되어 불완전한 다운로드 이미지가 발생합니다. org.apache.commons.io.ioutils.tobytearray (urlconnection.openstream ())을 사용하여 // byte [] bytes = ioutils.tobytearray (is); // new Byte [is.available ()]; 획득 된 바이트 // 스트림의 데이터는 바이트 배열로 읽습니다. 읽은 후 스트림의 데이터는 piclist.put (filename+". jpg", is)으로 지워집니다. // 현재 스트림이 파일에 기록되지 않으므로 스트림을 닫지 않아야합니다. 그렇지 않으면 스트림의 데이터가 손실됩니다. //is.close (); } true를 반환합니다. } catch (예외 e) {e.printstacktrace (); 거짓을 반환합니다. } 마침내 {// 스트림은 닫을 수 없습니다/*if (null! = is) {is.close (); }*/}}} 위의 압축을 위해 스트림을 사용하여 또 다른 문제가 발생했습니다. 파일을 압축 할 때 java.net.socketexception : Connection Reset
이유를 분석 한 후 스트림 inputStream 및 urlconnection이 연결 상태에 있고 URLConnection 시간 초과 재설정으로 인해 입력 스트림이 얻지 못합니다.
UrlConnection의 시간 초과 시간을 설정하려고했지만 테스트 중에 수신 된 이미지 다운로드의 네트워크 속도가 크게 영향을 받았다는 것을 알았습니다. 이 방법은 매우 불안정하고 바람직하지 않습니다. 결국 스트림을 사용하여 포기하고 바이트 배열을 사용하여 압축 도구 클래스로 전달한 다음 바이트 배열을 스트림 압축으로 변환했습니다.
/ ***컨테이너를 사용하여 다운로드 된 이미지 바이트 배열*/ public boolean downpicture (list <eptry <string, String >> addrlist) 예외 {inputStream is = null; fileoutputStream fos = null; url url = null; 문자열 filename = null; 문자열 picaddr = null; 파일 pic = null; try {for (map.entry <string, string> addrentry : addrlist) {filename = addrentry.getKey (); picaddr = addrentry.getValue (); // URL 객체 생성 URL = new URL (picaddr); // 연결을 열고 java.net.urlConnection 객체를 만듭니다. 이 객체에는 연결을 닫는 방법이 없습니다. 서브 클래스 httpurlconnection으로 변환하여 연결 해제 메소드를 호출하여 연결을 닫을 수 있습니다. //java.net.urlconnection 및 java.net.httpurlConnection 연결을 닫기위한 시간 초과 설정 세트 // httpurlConnection uc = (httpurlConnection) url.openConnection (); is = uc.getInputStream (); // URLConnection에 의해 얻은 스트림은 InputStream을 통해 바이트 배열로 직접 기록되며 데이터가 손실되어 불완전한 다운로드 이미지가 발생합니다. org.apache.commons.io.ioutils.tobytearray (urlconnection.openstream ())을 사용하여 바이트를 해결하려면 [] bytes = ioutils.tobytearray (is); // new byte [is.available ()]; 스트림에서 얻은 바이트 // 데이터는 바이트 배열로 읽습니다. 읽은 후 스트림의 데이터가 지워지면 //is.read (bytes); piclist.put (filename+". jpg", bytes); is.close (); } true를 반환합니다. } catch (예외 e) {e.printstacktrace (); 거짓을 반환합니다. } 마침내 {if (null! = is) {is.close (); }}} 요약 :
구현 중에 발생하는 문제 :
1. 예를 들어, 공유 상태의 스레드 풀을 사용하는 경우, 여기에 저장된 이미지 바이트 데이터 컨테이너는 모든 스레드에서 공유되므로 동기화 된 컨테이너가 필요합니다. 그렇지 않으면 저장된 데이터에 문제가 발생합니다. 따라서 ConsurenThashMap <string, byte []>가 사용됩니다.
2. 메인 스레드의 실행 순서와 자식 스레드의 실행 순서에 문제가 있습니다. 기본 스레드는 스레드 풀의 모든 스레드가 이미지를 압축하기 전에 이미지 다운로드를 완료 할 때까지 기다려야하기 때문입니다. 메인 스레드가 하위 스레드가 종료 될 때까지 대기하지 않고 압축 메소드가 아래쪽으로 실행되면 이미지가 누락되거나 압축 된 이미지가 없습니다. 따라서 CountdownLatch를 사용하여이를 구현하거나 Dead Loop을 사용하여 Closing Thread Pool 문에서 ThreadPool.isterminated ()를 확인하여 메인 스레드를 계속 실행하여 이미지를 압축 할 수 있습니다.
3. URLConnection에 의해 얻은 입력 스트림은 압축을 위해 압축 클래스로 직접 전송되기 때문에 연결 시간 초과가 재설정되는 상황이 있으므로 다운로드 된 스트림이 바이트 배열에 저장된 다음 압축 클래스에 전달되어 스트림을 사용할 때 예상치 못한 상황을 피하기 위해 압축 된 클래스에 전달됩니다.
4. urlConnection.openStream ()을 사용한 후 입력 스트림을 얻은 후, 바이트 배열로 변환 한 이미지는 불완전합니다. . org.apache.commons.io.ioutils.tobytearray (urlconnection.openstream ())을 사용하여 해결할 수 있습니다. 자세한 내용은 소스 코드를 읽고 구현을 볼 수 있습니다.
다음은 FTP 도구 클래스의 구현입니다.
import java.io.bufferedInputStream; import java.io.bufferedOutputStream; import java.io.fileInputStream; import java.io.fileoutputStream; import java.io.ioexception; import org.apache.commons.net.ftp.ftpclient; import org.apache.commons.net.ftp.ftpclientConfig; import org.apache.commons.net.ftp.ftpconnectionClosedException; import org.apache.commons.net.ftp.ftpreply; 공개 클래스 ftputil2 {private ftpclient ftpclient = null; // FTP 서버 주소 개인 문자열 호스트 이름; // ftp 서버 기본 포트 public static int defaultport = 21; // 로그인 이름 개인 문자열 사용자 이름; // 비밀번호 로그인 비밀번호 개인 문자열 비밀번호; // 개인 문자열 remotedir에 액세스하는 원격 디렉토리; / ** * @param hostname * 호스트 주소 * @param port * 포트 번호 * @param username * username * @param password * password * @param remotedir * 기본 작업 디렉토리 * @param is_zhtimezone * @return * @return */ ** * new ftputil2 (propog). PropConfig.loadConfig ( "System.Properties"); 문자열 hostname = config.getConfig ( "ftpaddress"); 문자열 port = config.getConfig ( "ftpport"); 문자열 username = config.getConfig ( "ftpusername"); String password = config.getConfig ( "ftppassword"); 문자열 remotedir = config.getConfig ( "remoteFilePath"); 부울 IS_ZHTIMEZONE = true; this.hostname = hostname; this.username = username; this.password = 비밀번호; this.remotedir = remotedir == null? "": Remotedir; this.ftpclient = new ftpclient (); if (is_zhtimezone) {this.ftpclient.configure (ftputil2.config ()); this.ftpclient.setcontrolencoding ( "gbk"); } // login (); // 디렉토리를 전환 this.Changedir (this.remotedir); this.setFileType (ftpclient.binary_file_type); ftpclient.setdefaultport (integer.parseint (port)); } public ftputil2 (문자열 호스트 이름, int 포트, 문자열 사용자 이름, 문자열 비밀번호, 문자열 remotedir, boolean is_zhtimezone) {this.hostname = hostname; this.username = username; this.password = 비밀번호; defaultport = 포트; this.remotedir = remotedir == null? "": Remotedir; this.ftpclient = new ftpclient (); if (is_zhtimezone) {this.ftpclient.configure (ftputil2.config ()); this.ftpclient.setcontrolencoding ( "gbk"); } // this.login ()에 로그인; // 디렉토리를 전환 this.Changedir (this.remotedir); this.setFileType (ftpclient.ascii_file_type); ftpclient.setDefaultPort (포트); } / *** FTP 서버에 로그인* / public boolean login () {부울 성공 = false; try {ftpclient.connect (this.hostName, defaultport); ftpclient.login (this.username, this.password); int 답장; 답장 = ftpclient.getReplyCode (); if (! ftpReply.ispositiveCompletion (답장)) {ftpclient.disconnect (); 반환 성공; }} catch (ftpConnectionClosedException e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } success = true; System.out.println ( "FTP 서버에 연결 :" + this.hostName + "success..START 로그인"); 반환 성공; } private static ftpclientconfig config () {ftpclientConfig conf = new ftpclientConfig (ftpclientConfig.syst_unix); conf.setRecentDateFormatstr ( "mm month dd 날짜 HH : mm"); // conf.setRecentDateFormatstr ( "(yyyyy year)? mm month dd 날짜 (hh : mm)); 반환 콘크리트; } / ** * 작업 디렉토리 변경 * * @param remotedir * * / public void Changeir (String Remotedir) {try {this.remotedir = remotedir; ftpclient.changeworkingdirectory (Remotedir); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } system.out.println ( "작업 디렉토리 변경 :" + remotedir); } / ** * 이전 레벨 디렉토리로 돌아 가기 (부모 디렉토리) * / public void toparentDir () {try {ftpclient.changetoParentDirectory (); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }} / ***현재 작업 디렉토리에 모든 파일을 나열하십시오* / public string [] listAllFiles () {String [] names = this.listFiles ( "*"); reture this.sort (이름); } / ** * 지정된 작업 디렉토리에 일치하는 파일 목록 * * @param dir * exp : / cim / * @param file_regex * 와일드 카드는 * / public string [] listallFiles (문자열 dir, String file_regex) {string [] names = this.listfiles (dir + file_regex); reture this.sort (이름); } /** * 파일 일치하는 파일 목록 * * @param file_regex * 일치 문자, 와일드 카드 문자는 * /public string [] listfiles (String file_regex) {try { /** * ftpfile [] remotefiles = ftpclient.listfiles (file_regex); * //system.out.println(remotefiles.length); 문자열 [] name = new * String [RemoteFiles.Length]; if (remotefiles! = null) {for (int * i = 0; i <ormetfiles.length; i ++) {if (remotefiles [i] == null) * name [i] = ""; else * if (remoteFiles [i] .getName () == null || remoteFiles * [i] .getName (). equals * ( ".") || remoteFiles [i] .getName (). Equals ( "..") {name [i] = "" "; *} else name [i] = 원격 파일 [i] .getName (); * system.out.println (이름 [i]); }} */ ftpclient.enterlocalPassiveMode (); 문자열 [] name = ftpclient.listnames (file_regex) ;; if (name == null) 새 문자열을 반환합니다 [0]; reture this.sort (name); } catch (예외 e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); } 새 문자열을 반환합니다 [0]; } public void lists (string reg) {try {string [] a = ftpclient.listnames (reg); if (a! = null) {for (문자열 b : a) {system.out.println (b); }}} catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }} / ** * 전송 된 파일 유형 [텍스트 파일 또는 바이너리 파일] * * * @param fileType * ---Binary_File_Type, ascii_file_type * / public void setfileType (int fileType) {try {ftpclient.setFileType (filetype); } catch (ioexception e) {e.printstacktrace (); }}/ *** 파일 업로드** @param localfilepath* -local 파일 경로 + 파일 이름* @param newfilename* --- new 파일 이름*/ public void uploadfile (문자열 localFilePath, String NewFilename) {// this.ftPclient.EnterloCalPassiveMode (); try {buffin = new bufferedInputStream (new FileInputStream (localFilePath)); 부울 ifupload = ftpclient.storefile (NewFilename, Buffin); if (! ifupload) {System.out.println ( "파일을 업로드 실패 ..."); } else {system.out.println ( "파일을 성공적으로 업로드 ..."); }} catch (예외 e) {e.printstacktrace (); } 마침내 {try {if (buffin! = null) buffin.close (); } catch (예외 e) {e.printstacktrace (); }}}/ ** * 파일 업로드 2 * * @param 파일 * -fileInputStream 파일 * @param newfilename * --- 나오 파일 이름 */ public void newPloadFile (fileInputStream 파일, String NewFilename) {// 파일 this.ftpclient.enterlocalPassiveMode (); try {buffin = new bufferedInputStream (파일); 부울 ifupload = ftpclient.storefile (NewFilename, Buffin); if (! ifupload) {system.out.println ( "파일 업로드 실패 ..."); } else {system.out.println ( "파일 업로드 성공 ..."); }} catch (예외 e) {e.printstacktrace (); } 마침내 {try {if (buffin! = null) buffin.close (); } catch (예외 e) {e.printstacktrace (); }}}/ ** * 다운로드 파일 (단일) * * @param remoteFilename * -서버의 파일 이름 * @param localfilename * -local 파일 이름 */ public boolean downloadfile (string remoteFilename, String localFilename) {this.ftpclient.EnterLocalPassiveMode (); try {buffout = new bufferedOutputStream (new FileOutputStream (localFilename)); 부울 ifdownload = ftpclient .retrieveFile (RemoteFilename, Buffout); if (! ifdownload) {System.out.println ( "다운로드 파일 실패 ..."); 거짓을 반환합니다. } else {system.out.println ( "성공적으로 파일 다운로드 ..."); }} catch (예외 e) {e.printstacktrace (); 거짓을 반환합니다. } 마침내 {try {if (buffout! = null) buffout.close (); } catch (예외 e) {e.printstacktrace (); }} true를 반환합니다. } / *** ftp 연결을 닫습니다* / public void close () {try {if (ftpclient! = null) {ftpclient.logout (); ftpclient.disconnect (); }} catch (예외 e) {e.printstacktrace (); }} / ** * 버블 정렬 문자열 (큰에서 작은) * / public string [] sort (string [] str_array) {if (str_array == null) {throw new nullpointerexception ( "str_array는 null이 될 수 없습니다!"); } 문자열 tmp = ""; for (int i = 0; i <str_array.length; i ++) {for (int j = 0; str_array [j] = str_array [j + 1]; str_array [j + 1] = tmp; }}} return str_array; } public static void main (string [] strs) {ftputil2 ftputil2 = new ftputil2 ( "192.168.1.112", 20011, "test1", "test1", "/", true); ftputil2.downloadfile ( "test.txt", "d : //test.txt"); }}다음은 zip 도구 클래스입니다.
import java.io.file; import java.io.fileInputStream; import java.io.fileoutputStream; import java.io.ioexception; import java.io.inputstream; import java.io.outputStream; java.util.arraylist 가져 오기; java.util.enumeration 가져 오기; Java.util.list 가져 오기; java.util.map import; java.util.zip.zipentry import; import java.util.zip.zipfile; import java.util.zip.zipoutputstream; import org.apache.commons.io.ioutils; import com.ibatis.common.logging.log; import com.ibatis.common.logging.logfactory; 공개 클래스 ziputil {private static final log = logfactory.getLog (Ziputil.class); / *** 압축 파일** @param srcfile 파일 [] 압축 해야하는 파일 목록* @param zipfile 파일 압축 파일*/ public static outputstream zipfiles (list <file> srcfile, outputstream outputstream) {byte [] buf = new Byte [1024]; 시도 {// zip 파일 만들기 zipoutputstream out = new ZipoutputStream (outputStream); // 파일을 압축합니다 (int i = 0; i <srcfile.size (); i ++) {file file = srcfile.get (i); fileInputStream in = new FileInputStream (file); // 출력 스트림에 지퍼 항목을 추가합니다. out.putnextentry (new Zipentry (file.getName ())); // 파일에서 zip 파일로 바이트를 전송 int len; while ((len = in.read (buf))> 0) { //system.out.println(len+"================================================================================== =========================================================================================================================================== =========================================================================================================================================== =========================================================================================================================================== e) {log.error ( "Ziputil Zipfiles 예외 :"+e); return outputStream}}* @param srcfile 파일 [] 압축 해야하는 파일* / pubfile zipfiles (list <buyfile). BYTE [1024] {// ZipoutputStream을 만듭니다. out (ioException e) {log.error ( "Ziputil Zipfiles Exception :"+e); {// ZipoutputStream out = new ZipoutputStream (Zipfile); 출력 스트림을 추가합니다 zip out.close ()} catch (ioexception e) { "Ziputil Zipfiles 예외 :"+e); void ZipByArray (map <byte []> srcfile, file zipfile) {byte [] buf = new Byte [// ZipoutputStream out을 만듭니다 (map.entry <byte []> fileentry : srcfile.entryset () {// inputStream.getValue (); bytes = getValue (); out.write.closeentry (); system.out.println (e.getMessage ())}}}}* unzip** @param ZipFile 파일 파일 @param descdir string decompressed directory* / public wipfile, string descdir {// Zipfile Zf for zf (열거는 Zf.entries (); hasmoreElement () {// Zipentry entries.nextElement (); FileoutputStream (descdir + zipentryname) [1024]; "Ziputil unzipfiles 예외 :"+e)}}} * main */public static void main (string <file> srcfile = new arraylist <file> (); 파일 (d : //2.jpg). 위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.