问题
I am using the sample program here to build my code. Everything works fine with the local SFTP test server, When I tested today in my client SFTP servers, it gave me an exception as below.
When I debugged I saw the file being written with '.writing' extension on the client's SFTP server. The contents are fine, I don't see any issues with the file that was transferred but the file name is the issue now. After reading through the spring docs, I see that this is the temporary file extension, and the program tries to rename it back to the original name, but since the client SFTP does not provide this option, it throws and exception.
I tried writing the temporary-file-suffix=".writing" as temporary-file-suffix="" thinking that will set the options off, alas the same issue. Is there a work around?
One of the post mentions this, but no solution or the issue vanished for the user.
> 2014-07-28 20:11:21,564 [main] INFO com.jcraft.jsch - SSH_MSG_NEWKEYS
> sent 2014-07-28 20:11:21,608 [main] INFO com.jcraft.jsch -
> SSH_MSG_NEWKEYS received 2014-07-28 20:11:21,678 [main] INFO
> com.jcraft.jsch - SSH_MSG_SERVICE_REQUEST sent 2014-07-28 20:11:21,770
> [main] INFO com.jcraft.jsch - SSH_MSG_SERVICE_ACCEPT received
> 2014-07-28 20:11:21,818 [main] INFO com.jcraft.jsch - Authentications
> that can continue: publickey,keyboard-interactive,password 2014-07-28
> 20:11:21,818 [main] INFO com.jcraft.jsch - Next authentication
> method: publickey 2014-07-28 20:11:21,819 [main] INFO com.jcraft.jsch
> - Authentications that can continue: keyboard-interactive,password 2014-07-28 20:11:21,819 [main] INFO com.jcraft.jsch - Next
> authentication method: keyboard-interactive 2014-07-28 20:11:21,978
> [main] INFO com.jcraft.jsch - Authentication succeeded
> (keyboard-interactive). 2014-07-28 20:11:22,199 [main] DEBUG
> org.springframework.beans.factory.support.DefaultListableBeanFactory -
> Returning cached instance of singleton bean
> 'integrationEvaluationContext' 2014-07-28 20:11:22,878 [main] DEBUG
> org.springframework.integration.sftp.session.SftpSession - Initial
> File rename failed, possibly because file already exists. Will attempt
> to delete file: remote/TESTFILE.ABC and execute rename again.
> 2014-07-28 20:11:22,958 [main] INFO com.jcraft.jsch - Disconnecting
> from fsgatewaytest.aexp.com port 22 2014-07-28 20:11:22,961 [Connect
> thread fsgatewaytest.aexp.com session] INFO com.jcraft.jsch - Caught
> an exception, leaving main loop due to Socket closed Exception in
> thread "main" org.springframework.messaging.MessageDeliveryException:
> Error handling message for file [data/TESTFILE.ABC -> TESTFILE.ABC]
> at
> org.springframework.integration.file.remote.RemoteFileTemplate$1.doInSession(RemoteFileTemplate.java:227)
> at
> org.springframework.integration.file.remote.RemoteFileTemplate$1.doInSession(RemoteFileTemplate.java:190)
> at
> org.springframework.integration.file.remote.RemoteFileTemplate.execute(RemoteFileTemplate.java:302)
> at
> org.springframework.integration.file.remote.RemoteFileTemplate.send(RemoteFileTemplate.java:190)
> at
> org.springframework.integration.file.remote.RemoteFileTemplate.send(RemoteFileTemplate.java:182)
> at
> org.springframework.integration.file.remote.handler.FileTransferringMessageHandler.handleMessageInternal(FileTransferringMessageHandler.java:101)
> at
> org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
> at
> org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
> at
> org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
> at
> org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
> at
> org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
> at
> org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:255)
> at
> org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:223)
> at
> com.reachlocal.payment.integration.SftpOutboundTransferMain.main(SftpOutboundTransferMain.java:43)
> Caused by: org.springframework.messaging.MessagingException: Failed to
> write to 'inbox/REACHLOCALTST.CUFI.writing' while uploading the file
> at
> org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:397)
> at
> org.springframework.integration.file.remote.RemoteFileTemplate.access$500(RemoteFileTemplate.java:56)
> at
> org.springframework.integration.file.remote.RemoteFileTemplate$1.doInSession(RemoteFileTemplate.java:213)
> ... 13 more Caused by: org.springframework.core.NestedIOException:
> Failed to delete file inbox/TESTFILE.ABC; nested exception is
> org.springframework.core.NestedIOException: Failed to remove file: 2:
> Specified file path is invalid. at
> org.springframework.integration.sftp.session.SftpSession.rename(SftpSession.java:200)
> at
> org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:393)
> ... 15 more Caused by: org.springframework.core.NestedIOException:
> Failed to remove file: 2: Specified file path is invalid. at
> org.springframework.integration.sftp.session.SftpSession.remove(SftpSession.java:83)
> at
> org.springframework.integration.sftp.session.SftpSession.rename(SftpSession.java:194)
> ... 16 more
Updated config: Using use-temporary-file-name="false" solved this issue. Thanks a ton.
<int:channel id="inputChannel"/>
<int-sftp:outbound-channel-adapter id="sftpOutboundAdapter"
session-factory="sftpSessionFactory"
channel="inputChannel"
remote-filename-generator-expression="payload.getName()"
remote-directory="inbox"
use-temporary-file-name="false"/>
回答1:
How about this use-temporary-file-name?
In this case you end up with this:
try {
session.write(inputStream, tempFilePath);
// then rename it to its final name if necessary
if (useTemporaryFileName){
session.rename(tempFilePath, remoteFilePath);
}
}
From mentioned doc:
However, there may be situations where you don't want to use this technique (for example, if the server does not permit renaming files). For situations like this, you can disable this feature by setting use-temporary-file-name to false (default is true). When this attribute is false, the file is written with its final name and the consuming application will need some other mechanism to detect that the file is completely uploaded before accessing it.
来源:https://stackoverflow.com/questions/25008089/spring-integration-outbound-transfer-renaming-issues