我们可以使用 C# 在 FTP 服务器中解压缩文件吗

Posted

技术标签:

【中文标题】我们可以使用 C# 在 FTP 服务器中解压缩文件吗【英文标题】:Can we unzip file in FTP server using C# 【发布时间】:2017-08-29 09:26:20 【问题描述】:

我可以在 FTP 中提取 ZIP 文件并使用 C# 将此提取的文件放在同一位置吗?

【问题讨论】:

这是你的另一个选择***.com/a/8889126/2903863 【参考方案1】:

这是不可能的。

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#。

【讨论】:

有可能,见亚伦。 S. 上面的回答是如何解决问题的。 @NathanPrather Aaron 的答案将 ZIP 下载到本地计算机,提取单个文件并将其上传到服务器。这肯定不是大多数人在“在 FTP 服务器中解压缩文件” 下所想象的。 -- 所以,不,不可能按照 OP 的要求去做。 + 更不用说答案中的上传代码会破坏任何二进制文件。 --- 这并不意味着他的回答对某人(比如你)没有用。【参考方案2】:

通过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://***.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;
                        
                    
                
            
        
    

【讨论】:

但在内存流中解压缩后我必须将其上传到 ftp 对吗?实际上我希望所有这些都在一个 ftp 请求中完成.. 您的上传代码仅适用于文本文件 + ContentLength 不用于 FTP。 hmm,我使用的 MSDN 示例中使用了 ContentLength,所以如果不使用它,如您所建议的,为什么会这样? docs.microsoft.com/en-us/dotnet/framework/network-programming/… 和 zip 文件包含位图而不是文本文件 1) 即使是 MSDN 也可能是错误的。 2) 这意味着您在上传过程中损坏了位图。 @Aaron.S(我没有收到关于您的回复的通知,因为您没有使用@) - 绝对不是,只需在 .zip 中测试 .jpg。上传后会损坏。我已经用你的确切代码进行了测试,没有任何修改。【参考方案3】:

如果您试图在文件被 ftp 上传后解压缩文件,您将需要运行具有适当权限的服务器端脚本,该脚本可以从您的 c# 应用程序或 c# ssh 中触发,如前所述.

【讨论】:

以上是关于我们可以使用 C# 在 FTP 服务器中解压缩文件吗的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中解压缩多层 zip 文件

如何使用 Azure Function 在 Azure 文件共享中解压缩文件?

在 VB.net 中解压缩文件 [关闭]

如何使用内部 Windows XP 选项在 VBScript 中解压缩文件

在 Cordova 中解压缩多部分存档

等到文件在 .NET 中解锁