FTP - заливка файла

 
0
 
.NET
ava
CYBERDREAM | 12.11.2007, 11:51
Доброго времени суток всем.
Имеется принтер у которого поднят FTP. При попытки получить поток "Stream strm = reqFTP.GetRequestStream();" выскакивает ошибка:
The remote server returned an error: (550) File unavailable (e.g., file not found, no access)
Код следующий использую:

private static void up(string login, string pass, string path)
{
FileInfo fileInf = new FileInfo(path);
// string uri = null;
FtpWebRequest reqFTP;

//uri = "ftp://192.168.0.7/dest/d1prn/" + fileInf.Name;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://192.168.0.7/dest/d1prn/" + fileInf.Name)); //создаем файлик на серваке
reqFTP.Credentials = new NetworkCredential(login, pass);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;

reqFTP.Proxy = null;
reqFTP.UseBinary = true;
reqFTP.UsePassive = false;

reqFTP.ContentLength = fileInf.Length;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;

FileStream fs = fileInf.OpenRead();
try
{
Stream strm = reqFTP.GetRequestStream(); //Ошибка
contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}

strm.Close();
fs.Close();
}
catch (Exception ex)
{
Console.WriteLine("____>>>>"+ex.ToString());
}
}



Здесь http://www.rsdn.ru/Forum/?mid=2227639 пишут, что нужно разрешить CWD на стороне сервака, но в опциях принтера такого нету. Как быть народ?
P.S. через тотал и ком строку все пашет нормально
Comments (21)
ava
tol05 | 12.11.2007, 13:42 #
посмотри тут
смысл в том, чтобы послать команду "CWD" серверу вручную.
ava
CYBERDREAM | 12.11.2007, 14:47 #
За ссылочку спасибо.
Логинится без проблем. ПОменять директорию тоже. Но вот команду "PASV" не понимает и из командной строки тоже. Качал как то фтп клиент написанный на шарпе, та же беда. Но по идее пасивный режим не нужен, ибо мог прочитать все каталоге только в такой комбинации

reqFTP.UseBinary = true;
reqFTP.UsePassive = false;
ava
CYBERDREAM | 13.11.2007, 09:42 #
Вышеописанным макаром пока что не получилось осилить ФТП. Он работает в активном режиме, и комманду PASV не понимает. При наличии времени все таки надо осилить через этот класс, красивое решение. А на данный момент решил проблему с помощью библиотечки editFTP, в одной из тем по ФТП ее предлагали, но тогда я не увидел что можно менять ConnectionMode на ACTIVE.

Спасибо tol05 за ссылочку. smile
ava
0000 | 14.11.2007, 09:14 #
CYBERDREAM, а почему не через сокеты делаешь??
имхо лучше на уровне пониже - там можно явно послать байты...и никаких проблем не будет - сервер явно все поймет..
ava
CYBERDREAM | 14.11.2007, 09:46 #
0000 я только за, но увы не смог еще.
Меня как раз этот вариант идеально устраивает. Проблема в том, что сервер работает не в пассивном, а в активном режиме. Но ни команду ACTIVE ни PASV он не понимает, в этом то и загвоздка на данный момент. Через ком. строку эти команды так же воспринимаются как непонятные. smile
Думаю эту проблему решить можно, но пока еще не знаю как
ava
0000 | 14.11.2007, 10:38 #
через сокеты имхо проще, потому что лишних операций нет - подсоединился, послал запрос, обработал полученный ответ...все..чистая клиент-сервер...

reqFTP.UsePassive = true;

http://msdn2.microsoft.com/en-us/library/s...usepassive.aspx

помимо этого есть UseBinary, если понадобится бинарные файлы кидать

http://msdn2.microsoft.com/en-us/library/s....usebinary.aspx



кстати вот еще 2 интересные статейки про пассивный режим работы FTP и сравнение его с активным....
http://slacksite.com/other/ftp.html#passive
http://www.ncftp.com/ncftpd/doc/misc/ftp_a...PASVNATProblems
ava
CYBERDREAM | 14.11.2007, 10:49 #
В первом посте я указывал бинарный и активный режим. ПРоблема была в том, что он дирректорию не находил, как выяснилось это из-за того, что нужно слать команду CWD. В случае с сокетами именно так и выходит, но как правильно послать команду режима работы не пойму. Может специфика фтп сервака... Еще ньюанс пишу под фрэйм 1.1 на данный момент.

added later:
Ну а сокеты конечно рулят smile
ava
0000 | 14.11.2007, 10:55 #
так не понял..ты PASV включить не можешь на сервере или ему директорию сменить?
ava
CYBERDREAM | 14.11.2007, 10:57 #
Неуверен, что PASV можно включить на серваке, думаю в принтере все забито без возможностей изменений.
Сменить директорию чему?
ava
0000 | 14.11.2007, 11:11 #

class Program
{
static void Main(string[] args)
{
up("user", "user", "1.txt");
}
private static void up(string login, string pass, string path)
{
FileInfo fileInf = new FileInfo(path);

FtpWebRequest reqFTP;

reqFTP = (FtpWebRequest)FtpWebRequest.Create("ftp://192.168.1.10/1.txt"); //создаем файлик на серваке

reqFTP.Credentials = new NetworkCredential(login, pass);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.Proxy = null;
reqFTP.UsePassive = true;

StreamReader sourceStream = new StreamReader(fileInf.Name);
byte[] buff = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
if (fileInf.Length != buff.Length)
throw new Exception();

try
{
Stream strm = reqFTP.GetRequestStream();
strm.Write(buff, 0, buff.Length);
strm.Flush();
strm.Close();
}
catch (Exception ex)
{
Console.WriteLine("____>>>>" + ex.ToString());
}

FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();

Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);

response.Close();

Console.ReadLine();
}


вот тут с проксями и пассивным режимом можно еще поиграться....у меня и без них работает - на эмуляторе shhtps
ava
CYBERDREAM | 14.11.2007, 11:35 #
Увы та же история. Думаю это из-за жестких ограничений прав.
ava
0000 | 14.11.2007, 11:51 #
так...если не может вернуть поток, значит он может их не поддерживать..тут уже смотреть надо на сам сервер...а то может вообще зря пытаешься...

слушай..а ты хочешь, чтобы этот файл распечатался???..
по умолчанию файлы передаются в ASCII и не для печати..тебе надо явно тогда передать ему команду TYPE


если не поможет дай ему команду MODE S - посмотрим что вернет..эта команда переводит сервер в потоковый режим для передачи данных как поток байтов..

щас набросаю код с сокетами, проверим...

я просто не знаю как эти команды передать через FtpWebRequest
ava
0000 | 14.11.2007, 12:30 #
че-то коротенько не получилось, куча методов дополнительных вылезла по соединению и открыванию сокетов...
учти, что в этом примере я их нигде не закрывал - все убрал, так что надо будет - закроешь сам потом


using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
using System.Net;
using System.Net.Sockets;
using System.IO;
class Program
{
private static Socket CommandSocket;
private static Socket DataSocket;
private static byte[] ReceiveBuff = new byte[1024];
private static byte[] SendBuff = new byte[1024];

static void Main(string[] args)
{
// up("user", "user", "1.txt");
Connect();
UploadFile("1.txt");
Console.ReadLine();
}
private static void OpenCommandSocket()
{
try
{
IPAddress hostadd = Dns.GetHostEntry("192.168.1.10").AddressList[0];
IPEndPoint EPhost = new IPEndPoint(hostadd, 21);
CommandSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
CommandSocket.Connect(EPhost);
}
catch (SocketException e)
{
Console.WriteLine(e.ErrorCode.ToString());
}
}
private static void SendCommand(string command)
{
if (CommandSocket == null)
OpenCommandSocket();
byte[] sBuffer = Encoding.ASCII.GetBytes((command + "\r\n"));
try
{
CommandSocket.Send(sBuffer, sBuffer.Length, SocketFlags.None);
Console.WriteLine(command);
}
catch (SocketException ex)
{
Console.WriteLine(ex.ToString());
}
}
private static string ReceiveCommand()
{
string response = "";
int bytes = 0;
if (CommandSocket == null) OpenCommandSocket();
do
{
try
{
bytes = CommandSocket.Receive(ReceiveBuff, ReceiveBuff.Length, SocketFlags.None);
}
catch (SocketException e)
{
Console.WriteLine(e.ErrorCode);
}
response += Encoding.ASCII.GetString(ReceiveBuff, 0, bytes);
}
while (bytes > ReceiveBuff.Length);
Console.WriteLine(Encoding.ASCII.GetString(ReceiveBuff, 0, bytes));
return response;
}
private static bool ParseIPAdress(string IPString, out string ip, out int Port)
{
string ipData = null;
string[] tmp = null;
if ((IPString.IndexOf(',') != -1) && (IPString != null))
{
ipData = IPString.Substring(IPString.IndexOf('(') + 1, IPString.IndexOf(')') - IPString.IndexOf('(') - 1);
ipData = ipData.Replace(',', '.');
tmp = ipData.Split('.');
ip = tmp[0] + "." + tmp[1] + "." + tmp[2] + "." + tmp[3];
Port = int.Parse(tmp[4]) * 256 + int.Parse(tmp[5]);
return true;
}
else
{
ip = "127.0.0.1";
Port = 21;
return false;
}
}
private static void OpenDataSocket()
{
string ipAddress;
int ipPort;
SendCommand("PASV");
string ans = ReceiveCommand();

if (ParseIPAdress(ans, out ipAddress, out ipPort))
{
SendCommand("STRU F");
int answer = Convert.ToInt16(ReceiveCommand().Substring(0, 3));
if (answer == 200)
{
SendCommand("TYPE A");
answer = Convert.ToInt16(ReceiveCommand().Substring(0, 3));
if (answer == 200)
{
try
{
DataSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint EPhost = new IPEndPoint(Dns.GetHostEntry(ipAddress).AddressList[0], ipPort);
DataSocket.Connect(EPhost);
}
catch (SocketException e)
{
Console.WriteLine(e.ErrorCode.ToString());
}
}
}
}
}
public static void UploadFile(string fileName)
{
FileStream inp = new FileStream(fileName, FileMode.Open);
OpenDataSocket();

SendCommand("STOR " + System.IO.Path.GetFileName(fileName));
int answer = Convert.ToInt16(ReceiveCommand().Substring(0, 3));
if (answer == 125 || answer == 150)
{
int bytes;
while ((bytes = inp.Read(SendBuff, 0, (int)SendBuff.Length)) > 0)
{
try
{
DataSocket.Send(SendBuff, bytes, SocketFlags.None);
}
catch (SocketException ex)
{
Console.WriteLine(ex.ErrorCode.ToString());
}
}

}
}
private static void Connect()
{
try
{
int answer = Convert.ToInt16(ReceiveCommand().Substring(0, 3));
if (answer == 220)
{
SendCommand("USER " + "user");
answer = Convert.ToInt16(ReceiveCommand().Substring(0, 3));
switch (answer)
{
case 230:
break;
case 331:
SendCommand("PASS " + "user");
answer = Convert.ToInt16(ReceiveCommand().Substring(0, 3));
break;
case 332:
goto case 331;
}
}
}
catch (SocketException e)
{
Console.WriteLine(e.ErrorCode.ToString());
}
}
private static void up(string login, string pass, string path)
{
FileInfo fileInf = new FileInfo(path);

FtpWebRequest reqFTP;

reqFTP = (FtpWebRequest)FtpWebRequest.Create("ftp://192.168.1.10/1.txt"); //создаем файлик на серваке

reqFTP.Credentials = new NetworkCredential(login, pass);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.Proxy = null;
reqFTP.UsePassive = true;

StreamReader sourceStream = new StreamReader(fileInf.Name);
byte[] buff = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
if (fileInf.Length != buff.Length)
throw new Exception();

try
{
Stream strm = reqFTP.GetRequestStream(); //Ошибка
strm.Write(buff, 0, buff.Length);
strm.Flush();
strm.Close();
}
catch (Exception ex)
{
Console.WriteLine("____>>>>" + ex.ToString());
}

FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();

Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);

response.Close();

Console.ReadLine();
}

}
}

ava
CYBERDREAM | 14.11.2007, 14:02 #
Мне именно в бинэри нужно передавать, иначе принтер не поймет, и использовать именно активный режим, а не пассивный. Указанный пример как то решает проблему с тем, чтобы разрешить пассивный режим? или это как пример просто?
ava
0000 | 14.11.2007, 14:23 #
этот пример явно говорит серверу включить пассивный режим командой PASV...

если тебе нужен именно активный, чтобы клиент принимал соединение, то вместо команды PASV надо использовать команду
PORT h1,h2,h3,h4,p1,p2, где
IP адрес = h1.h2.h3.h4 и номер порта = (p1*256+p2), с которыми сервер должен устанавливать соединение для передачи данных.

но тут может быть еще куча тонкостей...например сервер может не дать установить активное соединение и принудительно ставить пассивное...

а передача бинарников - измени "TYPE A" на "TYPE I"
ava
0000 | 15.11.2007, 14:15 #
CYBERDREAM, поставил вопрос решен..как решил-то, что получилось? отпишись, плз! =)
ava
CYBERDREAM | 15.11.2007, 16:02 #
0000 спасибо огромное за помощь, но заняться через 2 часика только смогу им. На спех проверил предложенные тобою код, выдло сообщение ошибку в данном моменте:

Convert.ToInt16(ReceiveCommand().Substring(0, 3));

тобишь длина строки меньше 3, и вроде даже равна нулю, увы сейчас чуть заморочен другим делом, но как сказал через 2 часика займусь этим благим делом
ava
0000 | 15.11.2007, 16:35 #
связь с сервером....то есть ни одна команда не прошла??даже соединение?
ava
CYBERDREAM | 15.11.2007, 16:46 #
насколько я помню - нет, скоро дам точный ответ
ava
CYBERDREAM | 10.12.2007, 11:00 #
Много воды конечно утекло, но теперь могу полностью заняться этим вопросом. Пишу на фрейме 1.1, поэтому Generic не катят тут, плюс многие отличия от второго. Реально на 1.1 это написать?
ava
CYBERDREAM | 10.12.2007, 13:24 #
А под 2.0 до передачи файла все ок smile

PORT h1,h2,h3,h4,p1,p2
200 PORT command successful
STOR file
501 Permission denied

Залить можно лишь в определенную папку. Елси посылаю комманду cd dest/d1prn то выдает 500 'cd': command not understood
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
  0000   CYBERDREAM   tol05
advanced
Submit