📄 ftpclient.java
字号:
* bytes already transferred are skipped over, while for gets(), if
* writing to a file, it is opened in append mode, and only the bytes
* required are transferred.
*
* Currently resume is only supported for BINARY transfers (which is
* generally what it is most useful for).
*
* @throws FTPException
*/
public void resume() throws FTPException {
if (transferType.equals(FTPTransferType.ASCII))
throw new FTPException("Resume only supported for BINARY transfers");
resume = true;
}
/**
* Cancel the resume. Use this method if something goes wrong
* and the server is left in an inconsistent state
*
* @throws IOException
* @throws FTPException
*/
public void cancelResume()
throws IOException, FTPException {
restart(0);
resume = false;
}
/**
* Issue the RESTart command to the remote server
*
* @param size the REST param, the mark at which the restart is
* performed on the remote file. For STOR, this is retrieved
* by SIZE
* @throws IOException
* @throws FTPException
*/
private void restart(long size)
throws IOException, FTPException {
FTPReply reply = control.sendCommand("REST " + size);
lastValidReply = control.validateReply(reply, "350");
}
/**
* Put a local file onto the FTP server. It
* is placed in the current directory.
*
* @param localPath path of the local file
* @param remoteFile name of remote file in
* current directory
*/
public void put(String localPath, String remoteFile)
throws IOException, FTPException {
put(localPath, remoteFile, false);
}
/**
* Put a stream of data onto the FTP server. It
* is placed in the current directory.
*
* @param srcStream input stream of data to put
* @param remoteFile name of remote file in
* current directory
*/
public void put(InputStream srcStream, String remoteFile)
throws IOException, FTPException {
put(srcStream, remoteFile, false);
}
/**
* Put a local file onto the FTP server. It
* is placed in the current directory. Allows appending
* if current file exists
*
* @param localPath path of the local file
* @param remoteFile name of remote file in
* current directory
* @param append true if appending, false otherwise
*/
public void put(String localPath, String remoteFile,
boolean append)
throws IOException, FTPException {
// get according to set type
if (getType() == FTPTransferType.ASCII) {
putASCII(localPath, remoteFile, append);
}
else {
putBinary(localPath, remoteFile, append);
}
validateTransfer();
}
/**
* Put a stream of data onto the FTP server. It
* is placed in the current directory. Allows appending
* if current file exists
*
* @param srcStream input stream of data to put
* @param remoteFile name of remote file in
* current directory
* @param append true if appending, false otherwise
*/
public void put(InputStream srcStream, String remoteFile,
boolean append)
throws IOException, FTPException {
// get according to set type
if (getType() == FTPTransferType.ASCII) {
putASCII(srcStream, remoteFile, append);
}
else {
putBinary(srcStream, remoteFile, append);
}
validateTransfer();
}
/**
* Validate that the put() or get() was successful. This method is not
* for general use.
*/
public void validateTransfer()
throws IOException, FTPException {
checkConnection(true);
// check the control response
String[] validCodes = {"225", "226", "250", "426", "450"};
FTPReply reply = control.readReply();
// permit 426/450 error if we cancelled the transfer, otherwise
// throw an exception
String code = reply.getReplyCode();
if ( (code.equals("426")||code.equals("450")) && !cancelTransfer )
throw new FTPException(reply);
lastValidReply = control.validateReply(reply, validCodes);
}
/**
* Close the data socket
*/
private void closeDataSocket() {
if (data != null) {
try {
data.close();
data = null;
}
catch (IOException ex) {
log.warn("Caught exception closing data socket", ex);
}
}
}
/**
* Request the server to set up the put
*
* @param remoteFile name of remote file in
* current directory
* @param append true if appending, false otherwise
*/
private void initPut(String remoteFile, boolean append)
throws IOException, FTPException {
checkConnection(true);
// reset the cancel flag
cancelTransfer = false;
boolean close = false;
data = null;
try {
// set up data channel
data = control.createDataSocket(connectMode);
data.setTimeout(timeout);
// if resume is requested, we must obtain the size of the
// remote file and issue REST
if (resume) {
if (transferType.equals(FTPTransferType.ASCII))
throw new FTPException("Resume only supported for BINARY transfers");
resumeMarker = size(remoteFile);
restart(resumeMarker);
}
// send the command to store
String cmd = append ? "APPE " : "STOR ";
FTPReply reply = control.sendCommand(cmd + remoteFile);
// Can get a 125 or a 150
String[] validCodes = {"125", "150"};
lastValidReply = control.validateReply(reply, validCodes);
}
catch (IOException ex) {
close = true;
throw ex;
}
catch (FTPException ex) {
close = true;
throw ex;
}
finally {
if (close) {
resume = false;
closeDataSocket();
}
}
}
/**
* Put as ASCII, i.e. read a line at a time and write
* inserting the correct FTP separator
*
* @param localPath full path of local file to read from
* @param remoteFile name of remote file we are writing to
* @param append true if appending, false otherwise
*/
private void putASCII(String localPath, String remoteFile, boolean append)
throws IOException, FTPException {
// create an inputstream & pass to common method
InputStream srcStream = new FileInputStream(localPath);
putASCII(srcStream, remoteFile, append);
}
/**
* Put as ASCII, i.e. read a line at a time and write
* inserting the correct FTP separator
*
* @param srcStream input stream of data to put
* @param remoteFile name of remote file we are writing to
* @param append true if appending, false otherwise
*/
private void putASCII(InputStream srcStream, String remoteFile,
boolean append)
throws IOException, FTPException {
// need to read line by line ...
LineNumberReader in = null;
BufferedWriter out = null;
long size = 0;
try {
in = new LineNumberReader(new InputStreamReader(srcStream));
initPut(remoteFile, append);
// get an character output stream to write to ... AFTER we
// have the ok to go ahead AND AFTER we've successfully opened a
// stream for the local file
out = new BufferedWriter(
new OutputStreamWriter(data.getOutputStream()));
// write \r\n as required by RFC959 after each line
long monitorCount = 0;
int ch = -1;
while ((ch = in.read()) != -1 && !cancelTransfer) {
size++;
monitorCount++;
if (ch == '\n')
out.write(FTPControlSocket.EOL);
else
out.write(ch);
if (monitor != null && monitorCount > monitorInterval) {
monitor.bytesTransferred(size);
monitorCount = 0;
}
}
}
finally {
try {
if (in != null)
in.close();
}
catch (IOException ignore) {}
try {
if (out != null) {
out.flush();
//out.close(); // Hans
}
}
catch (IOException ignore) {}
closeDataSocket();
// notify the final transfer size
if (monitor != null)
monitor.bytesTransferred(size);
}
}
/**
* Put as binary, i.e. read and write raw bytes
*
* @param localPath full path of local file to read from
* @param remoteFile name of remote file we are writing to
* @param append true if appending, false otherwise
*/
private void putBinary(String localPath, String remoteFile,
boolean append)
throws IOException, FTPException {
// open input stream to read source file ... do this
// BEFORE opening output stream to server, so if file not
// found, an exception is thrown
InputStream srcStream = new FileInputStream(localPath);
putBinary(srcStream, remoteFile, append);
}
/**
* Put as binary, i.e. read and write raw bytes
*
* @param srcStream input stream of data to put
* @param remoteFile name of remote file we are writing to
* @param append true if appending, false otherwise
*/
private void putBinary(InputStream srcStream, String remoteFile,
boolean append)
throws IOException, FTPException {
BufferedInputStream in = null;
BufferedOutputStream out = null;
long size = 0;
try {
in = new BufferedInputStream(srcStream);
initPut(remoteFile, append);
// get an output stream
out = new BufferedOutputStream(
new DataOutputStream(data.getOutputStream()));
// if resuming, we skip over the unwanted bytes
if (resume) {
in.skip(resumeMarker);
}
byte[] buf = new byte[transferBufferSize];
// read a chunk at a time and write to the data socket
long monitorCount = 0;
int count = 0;
while ((count = in.read(buf)) > 0 && !cancelTransfer) {
out.write(buf, 0, count);
size += count;
monitorCount += count;
if (monitor != null && monitorCount > monitorInterval) {
monitor.bytesTransferred(size);
monitorCount = 0;
}
}
}
finally {
resume = false;
try {
if (in != null)
in.close();
}
catch (IOException ignore) {}
// flush and clean up
try {
if (out != null) {
out.flush();
out.close(); // Hans XXXXXXX
}
}
catch (IOException ignore) {}
closeDataSocket();
// notify the final transfer size
if (monitor != null)
monitor.bytesTransferred(size);
// log bytes transferred
log.debug("Transferred " + size + " bytes to remote host");
}
}
/**
* Put data onto the FTP server. It
* is placed in the current directory.
*
* @param bytes array of bytes
* @param remoteFile name of remote file in
* current directory
*/
public void put(byte[] bytes, String remoteFile)
throws IOException, FTPException {
put(bytes, remoteFile, false);
}
/**
* Put data onto the FTP server. It
* is placed in the current directory. Allows
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -