سؤال

أنا أكتب عميل SFTP بسيط في PHP لأن لدينا الحاجة إلى استرداد الملفات برمجيا عبر خوادم N البعيدة. أنا أستخدم ملحق Pecl SSH2.

لقد ارتفعت ضد كتلة الطريق، رغم ذلك. تشير الوثائق الموجودة في PHP.NET إلى أنه يمكنك القيام بذلك:

$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');

ومع ذلك، لدي طريقة LS التي تحاول شيئا مشابها

public function ls($dir)
{
    $rd = "ssh2.sftp://{$this->sftp}/$dir";
    $handle = opendir($rd);
    if (!is_resource($handle)) {
        throw new SFTPException("Could not open directory.");
    }

    while (false !== ($file = readdir($handle))) {
        if (substr($file, 0, 1) != '.'){
            print $file . "\n";
        }
    }
    closedir($handle);
}

أحصل على الخطأ التالية:

PHP Warning:  opendir(): Unable to open ssh2.sftp://Resource id #5/outgoing on remote host

هذا منطقي مثالي لأن هذا ما يحدث عند إلقاء مورد إلى سلسلة. هل الوثائق خاطئة؟ حاولت استبدال المورد مع المضيف واسم المستخدم والمضيف ولم يعمل أيضا. أعرف أن المسار صحيح لأنه يمكنني تشغيل SFTP من سطر الأوامر ويعمل بشكل جيد.

هل حاول أي شخص آخر استخدام extenstion SSH2 مع SFTP؟ هل أفتقد شيئا واضحا هنا؟

تحديث:

أقوم بإعداد SFTP على جهاز آخر في المنزل ويعمل على ما يرام. لذلك، يجب أن يكون هناك شيء عن الخادم الذي أحاول الاتصال به لا يعمل.

هل كانت مفيدة؟

المحلول

عند الاتصال بخادم SFTP وتحتاج إلى الاتصال بالمجلد الجذر (على سبيل المثال لقراءة محتوى المجلد)، لا تزال تحصل على الخطأ عند استخدام "/" فقط بالمسار.

الحل الذي وجدته هو استخدام المسار "/./"، وهذا مسار صالح يشير إلى مجلد الجذر. هذا مفيد عندما يكون المستخدم الذي تقوم بتسجيل الدخول به إمكانية الوصول فقط إلى مجلد الجذر الخاص به وعدم توفر أي مسار كامل.

لذلك يجب أن يكون الطلب إلى الخادم عند محاولة قراءة محتويات مجلد الجذر شيء مثل هذا:

$rd = "ssh2.sftp://{$this->sftp}/./";

نصائح أخرى

للحصول على إصدارات PHP> 5.6.27 استخدام Intval ()

$sftpConnection = ssh2_connect($host);
$sftp = ssh2_sftp($sftpConnection);
$fp = fopen("ssh2.sftp://" . intval($sftp) . $remoteFile, "r");

https://bugs.php.net/bug.php؟id=73597.

أواجه مشكلة مماثلة. أفترض أنك تفعل شيئا مشابها لهذا:

    $dir = "ssh2.sftp://{$sftp}{$remote_dir}"; 
    $handle = opendir($dir);

متى $remote_dir هو المسار الكامل من الجذر ثم open_dir يعمل. لو $remote_dir فقط "/" أو "، ثم أحصل على خطأ" غير قادر على فتح "كما فعلت.

في حالتي، يبدو SSH يربط في المجلد الجذر بدلا من دليل "Home" كما يفعل FTP. لقد ذكرت أنه عملت على خادم مختلف، لذلك أتساءل عما إذا كانت مجرد مشكلة في التكوين.

أسهل طريقة للحصول على SFTP تعمل داخل PHP (حتى على Windows) دون تثبيت أي ملحق وما إلى ذلك هو phpseclib: http://ppseclib.sourceforge.net/ وبعد يتم تنفيذ الأشياء SSH بالكامل في فئة PHP.

أنت تستخدم مثل هذا:

<?php
include('Net/SFTP.php');

$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

echo $sftp->pwd();
?>

الوثائق الموجودة في تلك الصفحة تحتوي على خطأ. ألق نظرة على المثال هنا بدلا من ذلك: http://php.net/ssh2_sftp. - ما تحتاجه فعليا هو فتح مورد SFTP خاص باستخدام SSH2_SFTP () قبل استخدامه مع FOPEN (). ونعم، يبدو هذا تماما، على سبيل المثال "مورد # 24" عند تحويلها إلى سلسلة ... غريب بعض الشيء ولكن يبدو أنه يعمل.

تحذير آخر هو أن SFTP يبدأ في الدليل الجذر بدلا من الدليل الرئيسي للمستخدم البعيد، لذلك يجب أن يكون دائما مسارك عن بعد في URI واحدة مطلقة.

كان لدي نفس المشكلة، لكن يمكنني معرفة المشكلة.

في حالتي، عند الاتصال بالخادم، كنت ذاهبا إلى جذر الحساب، وبسبب تكوين الخادم لم أتمكن من الكتابة هناك.

لقد قمت بالاتصال بالحساب باستخدام Fireftp، لذلك يمكنني أن أرى أين كان جذر الحساب ... كان جذر الخادم.

اضطررت إلى تضمين المسار كله حتى المجلد الذي سمح لي بالكتابة، لذلك يمكنني حل المشكلة.

لذلك، نصيحتي هي الحصول على المسار باستخدام واجهة رسومية (استخدمت fireftp)، وأضف المسار كله إلى التعليمات البرمجية الخاصة بك.


$pathFromAccountRootFolderToMyDestinationFolder = '/Account/Root/Folder/To/My/Folder';
$stream = fopen("ssh2.sftp://".$sftp."/".$pathFromAccountRootFolderToMyDestinationFolder."/myFile.ext", 'r');

آمل أن يساعدك ذلك وأشخاص آخرين مع نفس المشكلة!

هتافات!

حاولت مؤخرا الحصول على SFTP على PHP العامل ووجدت أن phpseclib كان أسهل كثيرا:

http://ppseclib.sourceforge.net/

إذا كان لديك رفاهية عدم وجود مضيف مشترك ويمكنه تثبيت أي ملحقات تريد ربما سيكون ملحق Pecl أفضل ولكن ليس كلنا محظوظون للغاية. بالإضافة إلى ذلك، يبدو واجهة برمجة التطبيقات في Phpseclib أكثر بديهية بعض الشيء، والكوني OOP وكلها.

كانت مشكلتي، أنني كنت أتصل في الوظيفة وإرجاع عنوان URL السلسلة مع الموارد في الداخل. موارد مؤسسة من إنشاء سياق وظيفة ومجهدة القمامة هو قطع فصل المورد على نهاية الوظيفة. الحل: إرجاع الموارد حسب المرجع وإعلامها يدويا في سياق أكثر تعقيدا.

حل مشكلاتي عن طريق تمكين دعم SFTP على خادم (PowerShell)

هذا خطأ في حزمة SSH2 التي عثرت عليها منذ سنوات ونشرت رقعة إلى PHP.NET. إنه يعمل على إصلاح هذه المشكلة ولكنه يتطلب إعادة إنشاء حزمة Pecl SSH2. يمكنك قراءة المزيد هنا: https://bugs.php.net/bug.php؟id=69981.. وبعد قمت بتضمين تصحيح هناك إلى ملف SSH2_FOPEN_WRAPPERS.C في الحزمة لإصلاح المشكلة. هنا هو تعليق أدرجته:

فيما يلي خط التعليمات البرمجية من SSH2_FOPEN_WRAPPERS.C التي تسبب هذا الخطأ: (مشمول التعليق)

/*
       Find resource->path in the path string, then copy the entire string from the original path.
       This includes ?query#fragment in the path string
*/
    resource->path = estrdup(strstr(path, resource->path));

هذا الخط من التعليمات البرمجية - وبالتالي تم إدخال هذا الخطأ - كإصلاح لعلة # 59794. يحاول هذا الخط من التعليمات البرمجية الحصول على سلسلة تحتوي على الجزء والاستعلام والجزء من متغير المسار. النظر في هذه القيمة لمتغير المسار:

ssh2.sftp://Resource id #5/topdir?a=something#heading1

عندما يكون المسار "> المسار" / TOBDIR "، فإن النتيجة هي أن" / Topdir؟ A = شيء # يتجه 1 "يتم تعيينه للمورد -> المسار تماما مثل التعليق يقول.

الآن النظر في القضية عندما يكون المسار الموارد "/". بعد تنفيذ خط التعليمات البرمجية، يصبح Resource-> المسار "// معرف مورد # 5 / Topdir # Heading1". من الواضح أن هذا ليس ما تريد. إليك خط التعليمات البرمجية الذي يحدث:

 resource->path = estrdup( strstr( strstr( path, "//" ) + 2, "/" ) );

قد تحتاج أيضا إلى تطبيق التصحيح من أجل الخطأ رقم 73597 الذي يزيل "معرف المورد #" من سلسلة المسار قبل الاتصال php_url_parse ().

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top