Dropbox 文件夹下载问题 (c#)

Posted

技术标签:

【中文标题】Dropbox 文件夹下载问题 (c#)【英文标题】:Dropbox folder download issue (c#) 【发布时间】:2016-05-29 11:51:47 【问题描述】:

我通过网络链接自动从我的 Dropbox - storage(?) 下载整个文件夹,例如:https://www.dropbox.com/sh/bunchOfLetters/somthnsomthn?dl=1,只有一个基本的网络客户端:

using (WebClient wc = new WebClient())

     wc.DownloadFile(new Uri(uri), _basePath + localPath);

文件夹自然是 .rar 文件(由于 Dropbox 的下载系统),如果我尝试手动打开文件(通过 Winrar),则完全没有问题。现在问题来了....如果我尝试使用任何类型的自动库(如 unrar 或 SharpCompress),它总是给我一个“损坏的标题”,好像下载不会得到所有内容或文件刚刚坏了..但仍然用 Winrar 打开它就可以了。

如果有人知道如何以及为什么;很高兴听到你的想法。

编辑:

这是我用于 SharpCompress 的功能:

public static bool ExtractToFolder(string extractionPackage, string outputPath)
        
            if (extractionPackage == null) throw new ArgumentNullException(nameof(extractionPackage));
            if (outputPath == null) throw new ArgumentNullException(nameof(outputPath));
            if (string.IsNullOrEmpty(extractionPackage))
                throw new ArgumentException("Argument is null or empty", nameof(extractionPackage));
            if (string.IsNullOrEmpty(outputPath))
                throw new ArgumentException("Argument is null or empty", nameof(outputPath));
            if (!extractionPackage.EndsWith(".rar")) throw new InvalidDataException("not a .rar File");
            Directory.CreateDirectory(outputPath);

            try
            
                using (Stream stream = File.OpenRead(extractionPackage))
                using (RarReader reader = RarReader.Open(stream))
                
                    while (reader.MoveToNextEntry())
                    
                        reader.WriteEntryToDirectory(outputPath, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
                    
                

                return true;
            
            catch
            
                return false;
            
        

如果有人对 unrar 感兴趣: ..我知道它做得不好,但它仍然适用于普通文件......只是不是 Dropbox 的

namespace Cryptus.Rar

/// <summary>
/// just for compatibility purposes, use <see cref="SharpCompress"/>
/// </summary>
public class Unrar

    public enum RarOperations
    
        OP_EXTRACT = 0,
        OP_TEST = 1,
        OP_LIST = 2
    

    public const int ERAR_END_ARCHIVE = 10;
    public const int ERAR_NO_MEMORY = 11;
    public const int ERAR_BAD_DATA = 12;
    public const int ERAR_BAD_ARCHIVE = 13;
    public const int ERAR_UNKNOWN_FORMAT = 14;
    public const int ERAR_EOPEN = 15;
    public const int ERAR_ECREATE = 16;
    public const int ERAR_ECLOSE = 17;
    public const int ERAR_EREAD = 18;
    public const int ERAR_EWRITE = 19;
    public const int ERAR_SMALL_BUF = 20;

    public const int RAR_OM_LIST = 0;
    public const int RAR_OM_EXTRACT = 1;

    public const int RAR_SKIP = 0;
    public const int RAR_TEST = 1;
    public const int RAR_EXTRACT = 2;

    public const int RAR_VOL_ASK = 0;
    public const int RAR_VOL_NOTIFY = 1;

    [DllImport("unrar.dll")]
    public static extern IntPtr RAROpenArchive(ref RAROpenArchiveData ArchiveData);

    [DllImport("unrar.dll")]
    public static extern int RARCloseArchive(IntPtr hArcData);

    [DllImport("unrar.dll")]
    public static extern int RARReadHeader(IntPtr hArcData, ref RARHeaderData HeaderData);

    [DllImport("unrar.dll")]
    public static extern IntPtr RAROpenArchiveEx(ref RAROpenArchiveDataEx ArchiveData);

    [DllImport("unrar.dll")]
    public static extern int RARReadHeaderEx(IntPtr hArcData, ref RARHeaderDataEx HeaderData);

    [DllImport("unrar.dll")]
    public static extern int RARProcessFile(IntPtr hArcData, int Operation, string DestPath, string DestName);

    [DllImport("unrar.dll")]
    public static extern int RARGetDllVersion();

    [DllImport("user32.dll")]
    private static extern bool CharToOem(string lpszSrc, [Out] StringBuilder lpszDst);

    /// <summary>
    ///     opens an arcive and unloads its content to destDolder
    /// </summary>
    /// <param name="strFileName">input .rar File</param>
    /// <param name="destFolder">destination Folder</param>
    public void UnloadArchieve(string strFileName, string destFolder)
    
        IntPtr lHandle;
        int iStatus;
        RAROpenArchiveData uRAR = new RAROpenArchiveData();
        RARHeaderData uHeader = new RARHeaderData();

        uRAR.ArcName = strFileName + char.MinValue;
        uRAR.OpenMode = RAR_OM_EXTRACT;
        uRAR.CmtBuf = null;

        string ExtractDir = Path.GetDirectoryName(strFileName);
        StringBuilder sbDir = new StringBuilder();
        CharToOem(destFolder, sbDir);

        lHandle = RAROpenArchive(ref uRAR);
        if (uRAR.OpenResult != 0)
            Console.Write("Unable to open the Archieve!!!");
        while (RARReadHeader(lHandle, ref uHeader) == 0)
        
            int result = RARProcessFile(lHandle, 2, sbDir.ToString(), null);
            if (0 != result)
                Console.Write("Unable to open the Archieve!!!");
        


        iStatus = RARCloseArchive(lHandle);
    

    [StructLayout(LayoutKind.Sequential)]
    public struct RARHeaderData
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string ArcName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string FileName;
        public uint Flags;
        public uint PackSize;
        public uint UnpSize;
        public uint HostOS;
        public uint FileCRC;
        public uint FileTime;
        public uint UnpVer;
        public uint Method;
        public uint FileAttr;
        public string CmtBuf;
        public uint CmtBufSize;
        public uint CmtSize;
        public uint CmtState;
    

    [StructLayout(LayoutKind.Sequential)]
    public struct RAROpenArchiveData
    
        public string ArcName;
        public uint OpenMode;
        public uint OpenResult;
        public string CmtBuf;
        public uint CmtBufSize;
        public uint CmtSize;
        public uint CmtState;
    

    [StructLayout(LayoutKind.Sequential)]
    public struct RAROpenArchiveDataEx
    
        public string ArcName;
        public string ArcNameW;
        public uint OpenMode;
        public uint OpenResult;
        public string CmtBuf;
        public uint CmtBufSize;
        public uint CmtSize;
        public uint CmtState;
        public uint Flags;
        public uint Reserved;
    

    [StructLayout(LayoutKind.Sequential)]
    public struct RARHeaderDataEx
    
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string ArcName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string FileName;
        public string FileNameW;
        public uint Flags;
        public uint PackSize;
        public uint PackSizeHigh;
        public uint UnpSize;
        public uint UnpSizeHigh;
        public uint HostOS;
        public uint FileCRC;
        public uint FileTime;
        public uint UnpVer;
        public uint Method;
        public uint FileAttr;
        public string CmtBuf;
        public uint CmtBufSize;
        public uint CmtSize;
        public uint CmtState;
        public uint Reserved;
    

【问题讨论】:

能否提供给我们抛出异常的代码? 你能提供一个例子.rar文件吗?我以为 Dropbox 只生成 zip 文件。 @whymatter 它不像代码根本不工作,事实上它对所有其他 .rar 文件都工作正常.. 只是不是来自 Dropbox 的自动化......我仍然在广告 SharpCompress 功能 @SaculRennorb 当我这样做时,我得到一个 zip 文件。我之所以提到这一点是因为我想知道您获得的文件是否实际上是一个 ZIP 文件,就像它对我而言一样。 @smarx 我不这么认为,因为该文件实际上是一个。 rar 文件....明天我会尝试用 zip 标题打开它 【参考方案1】:

好吧,看来@smarx 的评论是对的!这有点奇怪,但 Dropbox 生成的 .rar 文件不包含 rar,而是包含 zip 标头。这对于任何形式的标题格式的自动检测都没有问题,但是如果您使用 rar 提取方法(应该用于 .rar 文件..),它将无法正常工作。

【讨论】:

以上是关于Dropbox 文件夹下载问题 (c#)的主要内容,如果未能解决你的问题,请参考以下文章

使用 curl 通过共享链接(不是公共链接)下载 Dropbox 文件夹

使用 Dropbox API 列出 Dropbox 的所有文件夹和文件

通过 wget 从 Dropbox 链接下载包含子文件夹的文件夹到 Unix 服务器

Dropbox 及其类似“文件夹”的设计

.NET C# 上的无服务器数据库 [关闭]

使用 cURL 下载受密码保护的 Dropbox 链接