Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SFTP put operation fails if used with remote file stream as resource #1177

Closed
mirfilip opened this issue Aug 29, 2017 · 7 comments
Closed

SFTP put operation fails if used with remote file stream as resource #1177

mirfilip opened this issue Aug 29, 2017 · 7 comments

Comments

@mirfilip
Copy link

mirfilip commented Aug 29, 2017

Hi,
I'm using version 2.0.6 of phpseclib via flysystem-sftp (bridge/adapter for flysystem).

I want to "stream" a remote file directly to sftp server, avoiding disk usage on a machine I run the script on. For that, I:

  1. fopen a remote file using http stream wrapper
  2. Executing SFTP::put with opened remote file handle as $data
$remoteFileStream = fopen(
    'http://www.example.org/someResource.mp4',
    'r'
);
$sftpFilesystem = new \phpseclib\Net\SFTP($host, $port, 30);
$loginSuccess = $sftpFileSystem->login($user, $pass);
if ($loginSuccess) {
   $success = $sftpFilesystem->put('/path/to/remote/file.mp4', $remoteFileStream);
   var_dump($success); // true but empty file is created
}

The result is an empty file created on sftp server.

Reading documentation, I have noticed a SOURCE_LOCAL_FILE mode. I have already seen #1119 which treats about somewhat similar case, but for local files.

Conceptually, I'd expect this case to handle that.

Is that the case that put with remote file as a stream is not supported?

@mirfilip
Copy link
Author

mirfilip commented Aug 30, 2017

Crux of the problem seems to be a failure of reading http stream stats with fstat. It returns false.

There is a disclaimer on docs page:

Note: This function will not work on remote files as the file to be examined must be accessible via the server's filesystem.

A simple snippet to reproduce:

$remoteFileStream = fopen(
    'http://www.example.org/',
    'r'
);
$stats = fstat($remoteFileStream);
var_dump($stats); // false

Of course, handling remote streams bears more questions like resumes via range header, efficiently copying it chunk by chunk, as it's not viable to just copy the remote stream to memory stream.

As this library can create and register a wrapper, I think it'd be possible to open a remote handle for sftp and do: stream_copy_to_stream($remoteFileStream, $sftpFileStream) or equivalent.

@bantu
Copy link
Member

bantu commented Aug 30, 2017 via email

@mirfilip
Copy link
Author

Here is my usage example of stream wrapper:

<?php
$remoteFileStream = fopen(
    'http://www.example.org/,
    'r'
);

$to = "test123.txt";
\phpseclib\Net\SFTP\Stream::register();
$sftpFilesystem = new \phpseclib\Net\SFTP($hostname, $port, 30);
if (!$sftpFilesystem->login($user, $pass)) {
    exit(1);
}

$context = [
    'sftp' => [
        'sftp' => $sftpFilesystem
    ],
];
$sftpStream = fopen("sftp://upload/$to", 'w+', null, stream_context_create($context));
if (!$sftpStream) {
    exit(1);
}

$bytes = stream_copy_to_stream($remoteFileStream, $sftpStream);

if ($bytes > 0) {
 exit(0);
} else {
    exit(1);
}

It indeed works, but file gets uploaded to root directory instead. I'm fiddling with that nuisance now.

@bantu
Copy link
Member

bantu commented Aug 31, 2017 via email

@mirfilip
Copy link
Author

mirfilip commented Aug 31, 2017

@bantu 👏
Indeed, changing to fopen("sftp://./upload/$to", 'w+, ...) handles that. I pass host, port, user, pass directly to SFTP instance.

I just wish interaction via Stream wrapper was documented. Maybe I'll contribute with some simplest use case.

Also, how about disallowing using remote streams with SFTP methods if they don't handle them? At very least, I feel it should return success false in that case.

terrafrost added a commit to terrafrost/phpseclib that referenced this issue Sep 6, 2017
@terrafrost
Copy link
Member

deb485c seemed to fix the issue for me.

@mirfilip
Copy link
Author

mirfilip commented Sep 7, 2017

@terrafrost Thank you.

I confirm deb485c fixes the issue.

Now using a stream wrapper and put both work.

@mirfilip mirfilip closed this as completed Sep 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants