private void InternalUploadFile(Stream input, string path, SftpUploadAsyncResult asynchResult, Flags flags) { if (input == null) throw new ArgumentNullException("input"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var fullPath = this._sftpSession.GetCanonicalPath(path); var handle = this._sftpSession.RequestOpen(fullPath, flags); ulong offset = 0; var buffer = new byte[this.BufferSize]; var uploadCompleted = false; do { var bytesRead = input.Read(buffer, 0, buffer.Length); if (bytesRead < this.BufferSize) { var data = new byte[bytesRead]; Buffer.BlockCopy(buffer, 0, data, 0, bytesRead); using (var wait = new AutoResetEvent(false)) { this._sftpSession.RequestWrite(handle, offset, data, wait); } uploadCompleted = true; } else { this._sftpSession.RequestWrite(handle, offset, buffer, null); } offset += (uint)bytesRead; // Call callback to report number of bytes read if (asynchResult != null) { asynchResult.Update(offset); } } while (!uploadCompleted); this._sftpSession.RequestClose(handle); }
public void SftpUploadAsyncResultConstructorTest() { AsyncCallback asyncCallback = null; // TODO: Initialize to an appropriate value object state = null; // TODO: Initialize to an appropriate value SftpUploadAsyncResult target = new SftpUploadAsyncResult(asyncCallback, state); Assert.Inconclusive("TODO: Implement code to verify target"); }
/// <summary> /// Begins an asynchronous uploading the steam into remote file. /// </summary> /// <param name="input">Data input stream.</param> /// <param name="path">Remote file path.</param> /// <param name="canOverride">if set to <c>true</c> then existing file will be overwritten.</param> /// <param name="asyncCallback">The method to be called when the asynchronous write operation is completed.</param> /// <param name="state">A user-provided object that distinguishes this particular asynchronous write request from other requests.</param> /// <param name="uploadCallback">The upload callback.</param> /// <returns> /// An <see cref="IAsyncResult" /> that references the asynchronous operation. /// </returns> /// <exception cref="ArgumentNullException"><paramref name="input" /> is <b>null</b>.</exception> /// <exception cref="ArgumentException"><paramref name="path" /> is <b>null</b> or contains whitespace characters.</exception> /// <exception cref="SshConnectionException">Client is not connected.</exception> /// <exception cref="SftpPermissionDeniedException">Permission to list the contents of the directory was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception> /// <exception cref="SshException">A SSH error where <see cref="P:System.Exception.Message" /> is the message from the remote host.</exception> /// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception> /// <remarks> /// Method calls made by this method to <paramref name="input" />, may under certain conditions result in exceptions thrown by the stream. /// </remarks> public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback asyncCallback, object state, Action<ulong> uploadCallback = null) { CheckDisposed(); if (input == null) throw new ArgumentNullException("input"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); var flags = Flags.Write | Flags.Truncate; if (canOverride) flags |= Flags.CreateNewOrOpen; else flags |= Flags.CreateNew; var asyncResult = new SftpUploadAsyncResult(asyncCallback, state); ExecuteThread(() => { try { InternalUploadFile(input, path, flags, asyncResult, offset => { asyncResult.Update(offset); if (uploadCallback != null) { uploadCallback(offset); } }); asyncResult.SetAsCompleted(null, false); } catch (Exception exp) { asyncResult.SetAsCompleted(exp, false); } }); return asyncResult; }
/// <summary> /// Internals the upload file. /// </summary> /// <param name="input">The input.</param> /// <param name="path">The path.</param> /// <param name="flags">The flags.</param> /// <param name="asyncResult">An <see cref="IAsyncResult"/> that references the asynchronous request.</param> /// <param name="uploadCallback">The upload callback.</param> /// <exception cref="ArgumentNullException"><paramref name="input" /> is <b>null</b>.</exception> /// <exception cref="ArgumentException"><paramref name="path" /> is <b>null</b> or contains whitespace.</exception> /// <exception cref="SshConnectionException">Client not connected.</exception> private void InternalUploadFile(Stream input, string path, Flags flags, SftpUploadAsyncResult asyncResult, Action<ulong> uploadCallback) { if (input == null) throw new ArgumentNullException("input"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); var fullPath = _sftpSession.GetCanonicalPath(path); var handle = _sftpSession.RequestOpen(fullPath, flags); ulong offset = 0; // create buffer of optimal length var buffer = new byte[_sftpSession.CalculateOptimalWriteLength(_bufferSize, handle)]; var bytesRead = input.Read(buffer, 0, buffer.Length); var expectedResponses = 0; var responseReceivedWaitHandle = new AutoResetEvent(false); do { // Cancel upload if (asyncResult != null && asyncResult.IsUploadCanceled) break; if (bytesRead > 0) { #if TUNING var writtenBytes = offset + (ulong) bytesRead; #else if (bytesRead < buffer.Length) { // Replace buffer for last chunk of data var data = new byte[bytesRead]; Buffer.BlockCopy(buffer, 0, data, 0, bytesRead); buffer = data; } var writtenBytes = offset + (ulong)buffer.Length; #endif #if TUNING _sftpSession.RequestWrite(handle, offset, buffer, bytesRead, null, s => #else _sftpSession.RequestWrite(handle, offset, buffer, null, s => #endif { if (s.StatusCode == StatusCodes.Ok) { Interlocked.Decrement(ref expectedResponses); responseReceivedWaitHandle.Set(); // Call callback to report number of bytes written if (uploadCallback != null) { // Execute callback on different thread ExecuteThread(() => uploadCallback(writtenBytes)); } } }); Interlocked.Increment(ref expectedResponses); offset += (ulong) bytesRead; bytesRead = input.Read(buffer, 0, buffer.Length); } else if (expectedResponses > 0) { // Wait for expectedResponses to change _sftpSession.WaitOnHandle(responseReceivedWaitHandle, OperationTimeout); } } while (expectedResponses > 0 || bytesRead > 0); _sftpSession.RequestClose(handle); }
public void Upload() { if (Protocol == SSHTransferProtocol.SCP) { if (!ScpClt.IsConnected) { Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, Language.strSSHTransferFailed + Environment.NewLine + "SCP Not Connected!"); return; } ScpClt.Upload(new FileInfo(SrcFile), $"{DstFile}"); } if (Protocol == SSHTransferProtocol.SFTP) { if (!SftpClt.IsConnected) { Runtime.MessageCollector.AddMessage(Messages.MessageClass.ErrorMsg, Language.strSSHTransferFailed + Environment.NewLine + "SFTP Not Connected!"); return; } asyncResult = (SftpUploadAsyncResult)SftpClt.BeginUploadFile(new FileStream(SrcFile, Open), $"{DstFile}", asyncCallback); } }
/// <summary> /// Begins an asynchronous uploading the steam into remote file. /// </summary> /// <param name="input">Data input stream.</param> /// <param name="path">Remote file path.</param> /// <param name="canOverride">if set to <c>true</c> then existing file will be overwritten.</param> /// <param name="handler">The object that handles callbacks for transferred data.</param> /// <returns>An <see cref="IAsyncResult"/> that references the asynchronous operation.</returns> /// <exception cref="ArgumentNullException"><paramref name="input"/> is <b>null</b>.</exception> /// <exception cref="ArgumentException"><paramref name="path"/> is <b>null</b> or contains whitespace characters.</exception> /// <exception cref="SshConnectionException">Client is not connected.</exception> /// <exception cref="Renci.SshNet.Common.SftpPermissionDeniedException">Permission to list the contents of the directory was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception> /// <exception cref="Renci.SshNet.Common.SshException">A SSH error where <see cref="P:SshException.Message"/> is the message from the remote host.</exception> /// <remarks>Method calls made by this method to <paramref name="input"/>, may under certain conditions result in exceptions thrown by the stream.</remarks> public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, IFileTransferHandler handler, object state) { if (input == null) throw new ArgumentNullException("input"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); var flags = Flags.Write | Flags.Truncate; if (canOverride) flags |= Flags.CreateNewOrOpen; else flags |= Flags.CreateNew; // Ensure that connection is established. this.EnsureConnection(); AsyncCallback callback; if (handler != null) { callback = (r) => handler.TransferCompleted(); } else { callback = (r) => { }; } var asyncResult = new SftpUploadAsyncResult(callback, state); this.ExecuteThread(() => { try { this.InternalUploadFile(input, path, handler, flags); asyncResult.SetAsCompleted(null, false); } catch (Exception exp) { asyncResult.SetAsCompleted(exp, false); } }); return asyncResult; }
private void OnTransferProgressChanged(SftpUploadAsyncResult e) { if (ProgressChanged != null) { progress.ChangeProgress((int)e.UploadedBytes, true); ProgressChanged(progress); } }
/// <summary> /// Internals the upload file. /// </summary> /// <param name="input">The input.</param> /// <param name="path">The path.</param> /// <param name="flags">The flags.</param> /// <param name="uploadCallback">The upload callback.</param> /// <exception cref="System.ArgumentNullException">input</exception> /// <exception cref="System.ArgumentException">path</exception> /// <exception cref="ArgumentNullException"><paramref name="input" /> is <b>null</b>.</exception> /// <exception cref="ArgumentException"><paramref name="path" /> is <b>null</b> or contains whitespace.</exception> /// <exception cref="SshConnectionException">Client not connected.</exception> private void InternalUploadFile(Stream input, string path, Flags flags, SftpUploadAsyncResult asyncResult, Action<ulong> uploadCallback) { if (input == null) throw new ArgumentNullException("input"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); var fullPath = this._sftpSession.GetCanonicalPath(path); var handle = this._sftpSession.RequestOpen(fullPath, flags); ulong offset = 0; var buffer = new byte[this.BufferSize]; var bytesRead = input.Read(buffer, 0, buffer.Length); var expectedResponses = 0; var expectedResponsesLock = new object(); do { // Cancel upload if (asyncResult != null && asyncResult.IsUploadCanceled) break; if (bytesRead > 0) { if (bytesRead < this.BufferSize) { // Replace buffer for last chunk of data var data = new byte[bytesRead]; Buffer.BlockCopy(buffer, 0, data, 0, bytesRead); buffer = data; } var writtenBytes = offset + (ulong)buffer.Length; this._sftpSession.RequestWrite(handle, offset, buffer, null, (s) => { if (s.StatusCode == StatusCodes.Ok) { lock (expectedResponsesLock) { expectedResponses--; // Call callback to report number of bytes written if (uploadCallback != null) { // Execute callback on different thread this.ExecuteThread(() => { uploadCallback(writtenBytes); }); } Monitor.Pulse(expectedResponsesLock); } } }); lock (expectedResponsesLock) { expectedResponses++; } offset += (uint)bytesRead; bytesRead = input.Read(buffer, 0, buffer.Length); } else if (expectedResponses > 0) { // Wait for expectedResponses to change lock (expectedResponsesLock) { Monitor.Wait(expectedResponsesLock); } } } while (expectedResponses > 0 || bytesRead > 0); this._sftpSession.RequestClose(handle); }
/// <summary> /// Begins an asynchronous uploading the steam into remote file. /// </summary> /// <param name="input">Data input stream.</param> /// <param name="path">Remote file path.</param> /// <param name="asyncCallback">The method to be called when the asynchronous write operation is completed.</param> /// <param name="state">A user-provided object that distinguishes this particular asynchronous write request from other requests.</param> /// <returns>An <see cref="IAsyncResult"/> that references the asynchronous operation.</returns> /// <exception cref="ArgumentNullException"><paramref name="input"/> is null.</exception> /// <exception cref="ArgumentException"><paramref name="path"/> is null or contains whitespace characters.</exception> /// <exception cref="SshConnectionException">Client is not connected.</exception> /// <exception cref="Renci.SshNet.Common.SftpPermissionDeniedException">Permission to list the contents of the directory was denied by the remote host -or- a SSH command was denied by the server.</exception> /// <exception cref="Renci.SshNet.Common.SshException">A SSH error where <see cref="P:SshException.Message"/> is the message from the remote host.</exception> /// <remarks>Method calls made by this method to <paramref name="input"/>, may under certain conditions result in exceptions thrown by the stream.</remarks> public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback, object state) { if (input == null) throw new ArgumentNullException("input"); if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("path"); // Ensure that connection is established. this.EnsureConnection(); var asyncResult = new SftpUploadAsyncResult(asyncCallback, state); this.ExecuteThread(() => { try { this.InternalUploadFile(input, path, asyncResult); asyncResult.SetAsCompleted(null, false); } catch (Exception exp) { asyncResult.SetAsCompleted(exp, false); } }); return asyncResult; }