1. 파일 업로드 개요
웹 개발에서 파일 업로드 기능을 실현하려면 두 단계가 필요합니다.
1. 웹 페이지에 입력 항목을 업로드합니다
<form action = "#"method = "post"encType = "multipart/form-data"> <input type = "file"name "="filename1 "/> <br> <input type ="file "name ="filename2 "/> <br> <입력 유형 ="value = "upload"/> <form> <!-1. 양식은 2. inctipe attreation attrect attatate가되어야합니다. 이 값을 설정 한 후 브라우저가 파일을 업로드 할 때 파일 데이터를 HTTP 요청 메시지 본문에 첨부하고 MIME 프로토콜을 사용하여 업로드 된 파일을 설명하여 수신기가 구문 분석하고 업로드 된 데이터를 처리 할 수 있습니다. 3. 입력의 이름 속성을 설정해야합니다. 그렇지 않으면 브라우저가 업로드 된 파일 데이터를 보내지 않습니다. ->
2. 서블릿에서 파일 업로드 데이터를 읽고 서버 하드 디스크에 저장하십시오.
요청 객체는 클라이언트가 제출 한 데이터를 읽을 수있는 getInputStream 메소드를 제공합니다. 그러나 사용자는 동시에 여러 파일을 업로드 할 수 있으므로 서블릿 측면에서 업로드 된 데이터를 직접 읽고 해당 파일 데이터를 별도로 구문 분석하는 것이 매우 번거로운 작업입니다.
예를 들어, 다음은 파일을 업로드 할 때 인터셉트 된 브라우저에서 보낸 요청의 HTTP 프로토콜의 일부 내용입니다.
허용 : Zh-Hans-CN, Zh-Hans; Q = 0.5Content- 타입 : 멀티 파트/형태-데이터; 경계 = ------------------------- 7DFA01D1908A4UA-CPU : AMD64ACCEPT-ENCODING : GZIP, deflateUser-Agent : Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; RV : 11.0) Geckocontent : 653host : local-host : 653host : Keep-AlivePragma : No-Cachecookie : jsessionID = 11CEFF8E271AB62CE676B5A87B746B5F ---------------------------- 7DFA01D1908A4Content-Disposition : Form-Data; 이름 = "username"Zhangsan ------------------------------- 7dfa01d1908a44content-disposition : form-data; 이름 = "userPass"1234 --------------------------------- 7DFA01D1908A44Content indisposition : Form-Data; 이름 = "filename1"; filename = "c : /users/asus/desktop/upload.txt : text/plain this는 첫 번째 파일 내용입니다! ----------------------------- 7dfa01d1908a4content-disposition : form-data; 이름 = "filename1"; filename = "c : /users/asus/desktop/upload2.txt : text/plain this는 두 번째 파일 내용입니다! 안녕하세요 -------------------------- 7dfa01d1908a4--
위의 데이터에서 수동으로 나누고 데이터를 읽는 경우 강력하고 안정적인 프로그램을 작성하기가 어렵다는 것을 알 수 있습니다. 따라서 사용자가 업로드 데이터를 처리 할 수 있도록 Apache 오픈 소스 조직은 파일 업로드를 처리하는 데 사용되는 오픈 소스 구성 요소 (Commons-Fileupload)를 제공합니다. 이 구성 요소는 우수한 성능을 가지고 있으며 API는 사용하기가 매우 간단하므로 개발자는 웹 파일 업로드 기능을 쉽게 구현할 수 있습니다. 따라서 웹 개발에서 파일 업로드 기능은 일반적으로 Commons-FileUpload 구성 요소를 사용하여 구현됩니다.
Commons-Fileupload, Commons-Io의 두 개의 JAR 패키지를 가져와야합니다
response.setContentType ( "text/html; charset = utf-8"); // 응답 인코딩 요청 .setcharacterencoding ( "UTF-8"); printwriter writer = response.getwriter (); // 응답 출력 스트림 시작 servletinputStream inputStream = request.getInputStream (); // request input stream/** 1. 디스크 파일 요소 객체를 만들고, 버퍼 크기를 설정하고 임시 파일 디렉토리를 설정하고, 하나는 매개 변수가없는 두 가지 구성 요소가 있습니다. Sizethreshold,이 매개 변수는 메모리 버퍼의 크기를 설정하고 기본값은 10K입니다. 업로드 파일이 버퍼 크기보다 크면 FileUpload 구성 요소는 임시 파일 캐시* @param java.io.file repository를 사용하여 파일을 업로드합니다. * * 매개 변수가없는 생성자가 사용되는 경우 setSizetHreshold (int sizethreshold), setRepository (java.io.file repository) * 메소드는 수동으로 설정됩니다 */ diskfileitemfactory factory = new DiskFileItemFactory (); int sizethreshold = 1024*1024; Factory.setsizethreshold (Sizethreshold); file repository = 새 파일 (request.getSession (). getServletContext (). getRealPath ( "temp")); // system.out.println (request.getSession (). getServletContext (). getRealPath ( "temp")); // system.out.out.println ( "temp")); Factory.SetRepository (저장소); / * * 2. DiskFileItemFactory 객체를 사용하여 ServletFileUpload 객체를 생성하고 업로드 된 파일의 크기를 설정하십시오 * * ServletFileUpload 객체는 업로드 된 파일 데이터를 처리하고 양식의 각 입력 항목을 파일로 캡슐화 할 책임이 있습니다. *이 개체의 일반적인 방법은 다음과 같습니다. 업로드 된 양식이 멀티 파트/양식-데이터 유형* 목록 Parserequest (요청)인지 결정합니다. 요청 객체를 구문 분석하고 양식의 각 입력 항목을 파일 시민 객체로 감고 모든 fileItems* void setfilesizemax (long filesizemax)를 저장하는 목록 컬렉션을 반환합니다. 단일 업로드 된 파일의 최대 값을 설정* void setsizemax (long sizemax); 업로드 된 Wenjiang* void setheaderencoding ()의 최대 값을 설정합니다. 파일 이름 업로드 된 코드 업로드 문제를 해결하기 위해 인코딩 형식을 설정하십시오. upload.setheaderencoding ( "UTF-8"); // 파일 이름 업로드 문제를 해결하기 위해 인코딩 형식을 설정하십시오./** 3. servletfileUpload.parserequest 메서드를 호출하여 요청 오브젝트를 구문 분석하고 모든 업로드 된 컨텐츠를 저장하는 목록 객체를 얻습니다*/list <fileitem> parserequest = null; try {parserequest = upload.parserequest (요청); } catch (fileUploadeXception e) {e.printstacktrace (); } / * * 4. 목록을 반복하십시오. 각각의 파일 객체를 반복하고, isformfield 메소드를 호출하여 파일 업로드인지를 결정합니다* true는 정상적인 양식 필드임을 의미합니다. 그런 다음 getfieldName 및 GetString 메소드를 호출하여 필드 이름과 필드 값을 가져 오는 방법* false가 업로드 파일입니다. 그런 다음 getInputStream 방법을 호출하여 데이터 입력 방법을 호출하여 업로드 데이터를 읽는 데 사용됩니다. 이 객체의 방법은 다음과 같습니다. * 부울 isformfield (); FileItem이 파일 업로드 객체인지 또는 일반 양식 객체 * true가 일반 양식 필드임을 의미합니다. * 그런 다음 getfieldName 및 GetString 메서드를 호출하여 필드 이름 및 필드 값 * false를 가져 오면 getName ()을 호출하여 업로드 파일의 파일 이름을 가져옵니다. 참고 : 일부 브라우저는 클라이언트 경로를 가지고 있으며 스스로를 빼야합니다. * 업로드 데이터 * delete ()를 읽으려면 데이터 입력 스트림을 얻으려면 getInputStream () 메소드를 호출합니다. FileItem 입력 스트림을 닫은 후 임시 파일 삭제가 삭제되었음을 의미합니다. */for (fileItem fileItem : parserequest) {if (fileItem.isformfield ()) {// if ( "username".Equals (fileItem.getFieldName ()))) {String username = fileItem.getString (); writer.write ( "사용자 이름 :"+username+"<br>"); } if ( "userPass".Equals (fileItem.getFieldName ())) {String UserPass = FileItem.getString (); writer.write ( "귀하의 비밀번호 :"+userPass+"<br>"); }} else {// 업로드 된 파일을 의미합니다. // 다른 브라우저에서 업로드 한 파일에는 경로 이름이있을 수 있으며 String ClientName = fileItem.getName (); 문자열 filename = ""; if (clientName.contains ( "//")) {// "/"가 경로가있는 이름을 의미하는 경우 마지막 파일 이름은 인터셉트 된 filename = clientName.SubString (clientName.LastIndexOf ( "//")). Substring (1); } else {filename = clientName; } uuid randomuuid = uuid.randomuuid (); // 128 비트 길이 전 세계적으로 고유 한 식별자 filename = randomuuid.toString ()+filename을 생성합니다. / * * 디렉토리 생성 알고리즘을 설계하십시오. 사용자가 업로드 한 총 파일 수가 수백만 배 이상의 주문이면 동일한 디렉토리에 넣으면 파일 인덱스가 매우 느려집니다. * 따라서 파일을 흩어진 방식으로 저장하기 위해 디렉토리 구조를 설계하고 합리적으로 * UUID 해시 알고리즘을 더 작은 범위로 변환하고 * UUID의 해시 코드를 8 비트 EG Octal 문자열로 변환합니다.이 문자열의 첫 비트에서 시작하여 각 캐릭터는 16 개의 하위 감독관을 대표합니다. 서버와 운영 체제 모두에 대한 효율적인 디렉토리 구조*/ int hashuuid = randomuuid.hashcode (); 문자열 hexuuid = integer.tohexstring (hashuuid); //system.out.println(HexUuid); // 업로드 된 파일을 String filepath = requestsession (). getServletContext (). getRealPath ( "Upload")에 저장할 폴더의 절대 경로를 가져옵니다. for (char c : hexuuid.tochararray ()) {filepath = filepath+"/"+c; } // 디렉토리가 존재하지 않으면 8 레벨 디렉토리 파일 filepathfile = 새 파일 (filepath)을 생성합니다. if (! filepathfile.exists ()) {filepathfile.mkdirs (); } // 요청 입력 스트림에서 파일을 읽고 Server inputStream inputStream2 = fileItem.getInputStream ()에 씁니다. // 서버 파일에서 파일을 만듭니다. 파일 파일 = 새 파일 (FilePath+"/"+filename); BufferedOutputStream BOS = New BufferedOutputStream (new FileOutputStream (file)); 바이트 [] 버퍼 = 새로운 바이트 [10*1024]; int len = 0; while ((len = inputStream2.read (buffer, 0, 10*1024))! = -1) {bos.write (buffer, 0, len); } writer.write ( "파일"+clientName+"가 성공적으로 <br>를 업로드했습니다); // 자원을 닫습니다 bos.close (); inputStream2.close (); }} // 업로드 된 Eclipse 파일은 Workspace의 프로젝트 디렉토리가 아닌 프로젝트 실행 디렉토리에 저장됩니다.2. 파일 업로드에 특별한주의가 필요한 문제 : (이러한 문제는 모두 위 코드에서 간단한 솔루션이 제공됩니다)
1. 파일을 저장하는 곳
서버의 보안을 보장하려면 업로드 된 파일을 응용 프로그램의 웹 -INF 디렉토리 또는 웹 서버에서 관리하지 않는 디렉토리에 저장해야합니다. 사용자가 JSP 파일과 같은 실행 가능한 코드로 파일을 업로드하고 스 플라이 싱 액세스 경로에 따라 액세스하면 서버 측에서 모든 것을 수행 할 수 있습니다.
2. 여러 사용자가 동일한 파일 이름으로 파일을 업로드하지 못하도록 파일 덮어 쓰기가 발생하여 파일 업 로더에 업로드 된 파일에 고유 한 파일 이름이 있는지 확인해야합니다 .
UUID + 사용자 업로드 파일 이름을 사용하여 이름을 바꿉니다
uuid에 대해 :
전 세계적으로 고유 한 식별자는 UUID (범용 고유 식별자)는 기계에서 생성 된 숫자를 나타냅니다. Open Software Foundation (OSF), 이더넷 카드 주소, Nanosecond Time, Chip ID 코드 및 가능한 많은 숫자가 설정 한 표준에 따르면 사용됩니다. 다음 부분의 조합으로 구성됩니다. 현재 날짜와 시간 (UUID의 첫 번째 부분은 시간과 관련이 있습니다. UUID를 생성 한 후 몇 초 동안 다른 UUID를 생성하면 첫 번째 부분이 다르고 나머지 부분은 동일합니다), 시계 시퀀스, 전 세계적으로 고유 한 IEEE 기계 식별 번호 (네트워크 카드가있는 경우, 네트워크 카드가 얻어지는 경우). 생성 된 결과 문자열은 비교적 길다는 것입니다.
일반적으로 16 진수로 표현 된 128 비트 길이 숫자입니다. 알고리즘의 핵심 아이디어는 기계의 네트워크 카드, 현지 시간 및 즉각적인 숫자와 함께 안내를 생성하는 것입니다. 이론적으로, 기계가 초당 100,000 개의 안내서를 생성하면 (확률의 의미에서) 3240 년이 반복되지 않을 것임을 보장 할 수 있습니다.
JDK1.5부터 UUID를 생성하는 것은 JDK가 UUID를 구현했다고 생각하면서 간단한 일이되었습니다.
java.util.uuid, 직접 전화하십시오.
uuid uuid = uuid.randomuuid ();
문자열 s = uuid.randomuuid (). tostring (); // 데이터베이스를 생성하는 데 사용되는 기본 키 ID는 매우 좋습니다. .
UUID는 16 자리 수로 구성되며
550E8400-E29B-11D4-A716-44655440000
3. 단일 디렉토리에서 너무 많은 파일을 방지하고 파일 읽기 및 쓰기 속도에 영향을 미치려면 파일 업로드를 처리하는 프로그램은 가능한 총 업로드 볼륨을 기반으로 적절한 디렉토리 구조 생성 알고리즘을 선택하고 업로드 된 파일을 분산 방식으로 저장해야합니다. 예를 들어 해시 코드 메소드를 사용하여 다단계 디렉토리를 작성하십시오.
4. 다른 사용자가 동일한 파일을 업로드하면 동일한 파일의 많은 사본을 서버 측에 저장할 필요가 없습니다. 이것은 자원 낭비입니다. 중복 파일의 문제를 해결하기 위해 알고리즘을 설계해야합니다.
5. JSP 기술 원리는 멀티 스레딩을 자동으로 구현합니다. 따라서 개발자는 파일 업로드의 다중 스레드 작업을 고려할 필요가 없습니다.
3. 파일 다운로드
<% arraylist <string> filenames = new ArrayList <string> (); filenames.add ( "file/aa.txt"); filenames.add ( "file/bb.jpg"); for (string filename : filenames) { %> <form action = "downloadservlet"method = "get"> <input type = "hidden"name = "filename"value = "< %= filename %>" /> <input type = "value ="download : < %= filename %> " /> < /form> < %}; 문자열 filename = request.getParameter ( "filename"); String urlname = urlencoder.encode (filename, "utf-8"); // 중국어 garbled 응답 방지 .setheader ( "content-disposition", "첨부 파일; filename ="+urlname); fileInputStream fis = new FileInputStream (새 파일 (request.getSession (). getServletContext (). getRealPath (filename)); bufferedInputStream bis = 새로운 bufferedInputStream (FIS); ServletOutputStream SOS = response.getOutputStream (); 바이트 [] 버퍼 = 새로운 바이트 [1024]; int len = 0; while ((len = bis.read (버퍼, 0, 1024))! = -1) {sos.write (buffer, 0, len); } bis.close (); fis.close ();4. SSH의 SmartUpload 구성 요소를 사용하여 파일 업로드 및 다운로드를 단순화하십시오.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.