오늘도 자바 포스팅을 써봅니다.
지금까지 에코 서버/클라이언트, 실시간 채팅 모두 다 텍스트로만 데이터를 전송했습니다
이번 시간에는 텍스트 뿐만 아니라 파일을 전송할 수 있는 예제를 올려봅니다.
자 그럼 잘 봐주세요~!!
서버.java
=========================================================
//3 - FTPServer 자체가 스레드되게 바로 스레드 상속
public class FTPServer extends Thread {
private ServerSocket server;
private Socket sock;
private String upDir="C:/MyJava/Upload";
private ObjectInputStream ois; // 파일명, 파일 등을 받을 수 있는 스트림
private FileOutputStream fos; // 파일로 내보내는 스트림 - (동영상, 이미지) 파일 형태는 1바이트 기반이 적합 / 문자 형태는 2바이트 기반
public FTPServer(){
try {
server=new ServerSocket(7788);
} catch (Exception e) {
e.printStackTrace();
}
}
public void run(){
out.println("FTPServer Started...");
try {
while(true){
sock=server.accept();
out.println(sock.getInetAddress()+"가 접속해옴");
ois=new ObjectInputStream(sock.getInputStream());
//서버가 파일명을 보내오는 것을 받자
String fileName=ois.readUTF(); // 문자열을 받기 위해 readUTF 사용
out.println(fileName);
String path=upDir+"/"+fileName; // 절대경로 지정
fos=new FileOutputStream(path); // 절대경로에 파일을 내보내어 생성한다.
//서버가 파일을 보내오는 것을 받자
int input=0, count=0; // count는 파일 크기 측정하기 위해
byte[] data=new byte[1024]; // 1kb씩. 빠르게 하려면 값을 더 크게 줘도 된다
//C:/MyJava/Upload 경로에 파일을 내보내기
while((input=ois.read(data))!=-1){
fos.write(data, 0, input);
fos.flush();
count+=input;
out.println(count+"byte 업로드중...");
}
if(fos!=null) fos.close();
if(ois!=null) ois.close();
if(sock!=null) sock.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
FTPServer fserver=new FTPServer();
fserver.start();
}
}
=========================================================
클라이언트.java
=========================================================
package net.day2;
import java.io.*;
import java.net.*;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
//3
//192.168.10.3
public class FileUploadGUI extends javax.swing.JFrame {
Socket sock;
ObjectOutputStream oos;
FileInputStream fis;
File file1;
PrintWriter pw;
public FileUploadGUI() {
initComponents();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
tfHost = new javax.swing.JTextField();
tfFile = new javax.swing.JTextField();
btFile = new javax.swing.JButton();
btUpload = new javax.swing.JButton();
lb = new javax.swing.JLabel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("FileUpload");
jPanel1.setBorder(new javax.swing.border.MatteBorder(null));
tfHost.setText("localhost");
tfHost.setBorder(javax.swing.BorderFactory.createTitledBorder("업로드 할 서버 IP 주소"));
tfFile.setBorder(javax.swing.BorderFactory.createTitledBorder("업로드 할 파일명"));
btFile.setText("파일찾기");
btFile.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btFileActionPerformed(evt);
}
});
btUpload.setText("Upload");
btUpload.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btUploadActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(tfFile)
.addComponent(tfHost, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(btFile, javax.swing.GroupLayout.DEFAULT_SIZE, 92, Short.MAX_VALUE)
.addComponent(btUpload, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(tfHost, javax.swing.GroupLayout.DEFAULT_SIZE, 54, Short.MAX_VALUE)
.addComponent(btUpload, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(btFile, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(tfFile, javax.swing.GroupLayout.DEFAULT_SIZE, 55, Short.MAX_VALUE))
.addContainerGap(25, Short.MAX_VALUE))
);
lb.setBorder(new javax.swing.border.SoftBevelBorder(javax.swing.border.BevelBorder.RAISED));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lb, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(lb, javax.swing.GroupLayout.PREFERRED_SIZE, 331, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(26, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
JFileChooser fileDial=new JFileChooser("C:/MyJava/"); // 기준 경로 지정
private void btFileActionPerformed(java.awt.event.ActionEvent evt) {
//파일 다이얼로그를 띄워 업로드할 파일을 선택한다
fileDial.showOpenDialog(this);
File selFile=fileDial.getSelectedFile();
tfFile.setText(selFile.getAbsolutePath());
String filename=selFile.getName();
//파일이 이미지 파일이면 lb에 미리보기를 해주자
filename=filename.toLowerCase(); // 파일 이름을 전부 소문자로 바꾸기
if(filename.endsWith(".jpg")||filename.endsWith(".png")||filename.endsWith(".gif")){
lb.setIcon(new ImageIcon(selFile.getAbsolutePath()));
lb.setText("");
lb.setHorizontalAlignment(JLabel.CENTER);
}
}
private void btUploadActionPerformed(java.awt.event.ActionEvent evt) {
// 파일을 서버에 전송하는 스레드 생성 및 동작
SenderThread tr=new SenderThread();
tr.start();
}
class SenderThread extends Thread{
public void run(){
// ftpserver에 접속하자(아이피, 포트번호)
String serverip=tfHost.getText();
int port=7788;
if(serverip==null||serverip.trim().isEmpty()){
JOptionPane.showMessageDialog(lb, "서버의 IP 주소를 입력하세요");
tfHost.requestFocus();
return;
}//if------
try{
// 소켓 생성
sock = new Socket(serverip, port);
// 타이틀에 연결 결과 출력
setTitle("##서버와 접속됨");
//소켓 출력스트림=>ObjectOutputStream 필터링
//클라이언트(OjbectInputStream)에게 파일을 보낸다
oos = new ObjectOutputStream(sock.getOutputStream());
//파일 입력스트림=>FileInputStream
//File chooser에서 선택한 파일을 읽어들인다
file1 = fileDial.getSelectedFile();
fis = new FileInputStream(file1);
//파일명을 서버에 전송한다.
String fname = file1.getName();
pw = new PrintWriter(sock.getOutputStream(),true);
oos.writeUTF(fname);
oos.flush();
//파일을 읽으면서 소켓출력 스트림을 통해 파일 데이터를 내보낸다.
int input=0, count=0;
byte[] data = new byte[1024];
while((input=fis.read(data))!=-1){
oos.write(data, 0, input);
oos.flush();
count+=input;
System.out.println(count+"바이트 전송중...");
}
if(pw!=null) pw.close();
if(oos!=null) oos.close();
if(fis!=null) fis.close();
if(sock!=null) sock.close();
JOptionPane.showMessageDialog(lb, "업로드 완료!");
}catch(Exception e){
System.out.println("예외: "+e);
}
}
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(FileUploadGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(FileUploadGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(FileUploadGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(FileUploadGUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new FileUploadGUI().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton btFile;
private javax.swing.JButton btUpload;
private javax.swing.JPanel jPanel1;
private javax.swing.JLabel lb;
private javax.swing.JTextField tfFile;
private javax.swing.JTextField tfHost;
// End of variables declaration
}
=========================================================
실행 결과 화면은 다음과 같습니다
서버를 실행하고 클라이언트를 실행하면 위와 같은 창이 나옵니다.
저는 제가 좋아하는 설현 움짤을 업로드 했습니다.
그리고 업로드 할 서버 IP 주소(자신의 IP) 주소를 적고
업로드 버튼을 누르면..
업로드가 완료됩니다.
이때 클라이언트, 서버 창에는 그동안 몇바이트를 업로드 했는지가 출력이 됩니다
위의 소스를 실행하기 위해서 반드시 'Upload' 라는 폴더가 있어야 합니다
그 폴더를 안만들고 백날 실행해봐야 되지 않습니다.
이 점 유의하시면서 이상 포스팅을 마칩니다
댓글 없음:
댓글 쓰기