【发布时间】:2017-08-29 09:26:20
【问题描述】:
我可以在 FTP 中提取 ZIP 文件并使用 C# 将此提取的文件放在同一位置吗?
【问题讨论】:
-
这是你的另一个选择stackoverflow.com/a/8889126/2903863
我可以在 FTP 中提取 ZIP 文件并使用 C# 将此提取的文件放在同一位置吗?
【问题讨论】:
这是不可能的。
FTP 协议中没有用于解压缩服务器上文件的 API。
但是,除了 FTP 访问之外,还具有 SSH 访问的情况并不少见。如果是这种情况,您可以通过 SSH 连接并在服务器上执行 unzip shell 命令(或类似命令)来解压文件。
见C# send a simple SSH command。
如果需要,您可以使用 FTP 协议下载提取的文件(尽管如果您有 SSH 访问权限,您也将拥有 SFTP 访问权限。然后,使用 SFTP 而不是 FTP。)。
一些(极少数)FTP 服务器提供 API 以使用 SITE EXEC 命令(或类似命令)执行任意 shell(或其他)命令。但这真的非常罕见。你可以像上面的 SSH 一样使用这个 API。
如果您想在本地下载和解压缩文件,您可以在内存中进行,而无需将 ZIP 文件存储到物理(临时)文件中。例如,请参阅How to import data from a ZIP file stored on FTP server to database in C#。
【讨论】:
通过FTP下载到MemoryStream,然后你就可以解压了,例子展示了如何获取流,只需更改为MemoryStream并解压。示例不使用 MemoryStream,但如果您熟悉流,修改这两个示例以适合您应该很简单。
示例来自:https://docs.microsoft.com/en-us/dotnet/framework/network-programming/how-to-download-files-with-ftp
using System;
using System.IO;
using System.Net;
using System.Text;
namespace Examples.System.Net
{
public class WebRequestGetExample
{
public static void Main ()
{
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://www.contoso.com/test.htm");
request.Method = WebRequestMethods.Ftp.DownloadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential ("anonymous","janeDoe@contoso.com");
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
Console.WriteLine(reader.ReadToEnd());
Console.WriteLine("Download Complete, status {0}", response.StatusDescription);
reader.Close();
response.Close();
}
}
}
解压流,例如来自:https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-compress-and-extract-files
using System;
using System.IO;
using System.IO.Compression;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
using (FileStream zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open))
{
using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
{
ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
{
writer.WriteLine("Information about this package.");
writer.WriteLine("========================");
}
}
}
}
}
}
这是一个从 ftp 下载 zip 文件,解压缩该 zip 文件,然后将压缩文件上传回同一 ftp 目录的工作示例
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string location = @"ftp://localhost";
byte[] buffer = null;
using (MemoryStream ms = new MemoryStream())
{
FtpWebRequest fwrDownload = (FtpWebRequest)WebRequest.Create($"{location}/test.zip");
fwrDownload.Method = WebRequestMethods.Ftp.DownloadFile;
fwrDownload.Credentials = new NetworkCredential("anonymous", "janeDoe@contoso.com");
using (FtpWebResponse response = (FtpWebResponse)fwrDownload.GetResponse())
using (Stream stream = response.GetResponseStream())
{
//zipped data stream
//https://stackoverflow.com/a/4924357
byte[] buf = new byte[1024];
int byteCount;
do
{
byteCount = stream.Read(buf, 0, buf.Length);
ms.Write(buf, 0, byteCount);
} while (byteCount > 0);
//ms.Seek(0, SeekOrigin.Begin);
buffer = ms.ToArray();
}
}
//include System.IO.Compression AND System.IO.Compression.FileSystem assemblies
using (MemoryStream ms = new MemoryStream(buffer))
using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Update))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
FtpWebRequest fwrUpload = (FtpWebRequest)WebRequest.Create($"{location}/{entry.FullName}");
fwrUpload.Method = WebRequestMethods.Ftp.UploadFile;
fwrUpload.Credentials = new NetworkCredential("anonymous", "janeDoe@contoso.com");
byte[] fileContents = null;
using (StreamReader sr = new StreamReader(entry.Open()))
{
fileContents = Encoding.UTF8.GetBytes(sr.ReadToEnd());
}
if (fileContents != null)
{
fwrUpload.ContentLength = fileContents.Length;
try
{
using (Stream requestStream = fwrUpload.GetRequestStream())
{
requestStream.Write(fileContents, 0, fileContents.Length);
}
}
catch(WebException e)
{
string status = ((FtpWebResponse)e.Response).StatusDescription;
}
}
}
}
}
}
}
【讨论】:
ContentLength 不用于 FTP。
@) - 绝对不是,只需在 .zip 中测试 .jpg。上传后会损坏。我已经用你的确切代码进行了测试,没有任何修改。
如果您试图在文件被 ftp 上传后解压缩文件,您将需要运行具有适当权限的服务器端脚本,该脚本可以从您的 c# 应用程序或 c# ssh 中触发,如前所述.
【讨论】: