public SimpleFTPDownloadInterface(SimpleFTP simpleFTP, final DownloadLink link, String filePath) { connectionHandler = new ManagedThrottledConnectionHandler(); final String host = SocketConnection.getHostName(simpleFTP.getSocket().getRemoteSocketAddress()); downloadable = new DownloadLinkDownloadable(link) { @Override public boolean isResumable() { return link.getBooleanProperty("RESUME", true); } @Override public void setResumeable(boolean value) { link.setProperty("RESUME", value); super.setResumeable(value); } @Override public String getHost() { return host; } }; if (!link.hasProperty(DownloadLink.PROPERTY_RESUMEABLE)) { downloadable.setResumeable(true); } this.filePath = filePath; logger = downloadable.getLogger(); downloadable.setDownloadInterface(this); this.simpleFTP = simpleFTP; }
protected void download(String filename, boolean resume) throws IOException, PluginException, SkipReasonException { final File file = outputPartFile; if (!simpleFTP.isBinary()) { logger.info("Warning: Download in ASCII mode may fail!"); } final InetSocketAddress pasv = simpleFTP.pasv(); resumed = false; if (resume) { final long resumePosition = file.length(); if (resumePosition > 0) { resumed = true; totalLinkBytesLoadedLive.set(resumePosition); simpleFTP.sendLine("REST " + resumePosition); try { simpleFTP.readLines(new int[] {350}, "Resume not supported"); downloadable.setResumeable(true); } catch (final IOException e) { cleanupDownladInterface(); if (e.getMessage().contains("Resume not")) { file.delete(); downloadable.setResumeable(false); throw new PluginException(LinkStatus.ERROR_RETRY); } throw e; } } } final RandomAccessFile raf; try { raf = IO.open(file, "rw"); } catch (final IOException e) { throw new SkipReasonException(SkipReason.INVALID_DESTINATION, e); } Socket dataSocket = null; MeteredThrottledInputStream input = null; try { dataSocket = simpleFTP.createSocket(new InetSocketAddress(pasv.getHostName(), pasv.getPort())); dataSocket.setSoTimeout(30 * 1000); simpleFTP.sendLine("RETR " + filename); simpleFTP.readLines(new int[] {150, 125}, null); input = new MeteredThrottledInputStream(dataSocket.getInputStream(), new AverageSpeedMeter(10)); connectionHandler.addThrottledConnection(input); if (resumed) { /* in case we do resume, reposition the writepointer */ totalLinkBytesLoaded = file.length(); raf.seek(totalLinkBytesLoaded); } else { totalLinkBytesLoaded = 0; } final byte[] buffer = new byte[32767]; int bytesRead = 0; while ((bytesRead = input.read(buffer)) != -1) { if (abort.get()) { break; } if (bytesRead > 0) { raf.write(buffer, 0, bytesRead); totalLinkBytesLoaded += bytesRead; totalLinkBytesLoadedLive.addAndGet(bytesRead); } } /* max 10 seks wait for buggy servers */ simpleFTP.getSocket().setSoTimeout(20 * 1000); simpleFTP.shutDownSocket(dataSocket); input.close(); try { simpleFTP.readLine(); } catch (SocketTimeoutException e) { LogSource.exception(logger, e); } } catch (SocketTimeoutException e) { LogSource.exception(logger, e); error( new PluginException( LinkStatus.ERROR_DOWNLOAD_INCOMPLETE, _JDT.T.download_error_message_networkreset(), LinkStatus.VALUE_NETWORK_IO_ERROR)); } catch (SocketException e) { LogSource.exception(logger, e); error( new PluginException( LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, _JDT.T.download_error_message_networkreset(), 1000l * 60 * 5)); } catch (ConnectException e) { LogSource.exception(logger, e); error( new PluginException( LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, _JDT.T.download_error_message_networkreset(), 1000l * 60 * 5)); } finally { close(raf); close(input); close(dataSocket); cleanupDownladInterface(); if (totalLinkBytesLoaded >= 0) { downloadable.setDownloadBytesLoaded(totalLinkBytesLoaded); } } }