Пример #1
0
        private void createDirCache(string localSyncDir)
        {
            DirectoryInfo di = new DirectoryInfo(localSyncDir);

            FileInfo[] fileInfos = di.GetFiles("*.*", SearchOption.AllDirectories);

            int originalCount = fileInfos.Length;

            List <string> files = new List <string>();

            string[] keys = new string[originalCount];
            bool[]   skip = new bool[originalCount];
            overwriteDict = new Dictionary <string, bool>();
            for (int i = 0; i < originalCount; ++i)
            {
                files.Add(fileInfos[i].FullName);

                if (syncSetting.UseShortFilename)
                {
                    keys[i] = syncSetting.SyncPrefix + fileInfos[i].Name;
                }
                else
                {
                    keys[i] = syncSetting.SyncPrefix + fileInfos[i].FullName;
                }

                skip[i] = false;
                overwriteDict.Add(fileInfos[i].FullName, false);
            }

            // 按照前缀/后缀跳过
            string[] skippedPrefixes = this.syncSetting.SkipPrefixes.Split(',');
            string[] skippedSuffixes = this.syncSetting.SkipSuffixes.Split(',');
            for (int i = 0; i < originalCount; ++i)
            {
                string shortFileName = fileInfos[i].Name;

                if (skip[i])
                {
                    continue;
                }
                if (shouldSkipByPrefix(shortFileName, skippedPrefixes))
                {
                    skip[i] = true;
                    addFileSkippedLog(string.Format("{0}\t{1}", this.syncSetting.TargetBucket, files[i]));
                    updateUploadLog("按照前缀规则跳过文件 " + files[i]);
                }

                if (skip[i])
                {
                    continue;
                }
                if (shouldSkipBySuffix(shortFileName, skippedSuffixes))
                {
                    skip[i] = true;
                    addFileSkippedLog(string.Format("{0}\t{1}", this.syncSetting.TargetBucket, files[i]));
                    updateUploadLog("按照后缀规则跳过文件 " + files[i]);
                }
            }

            // 检查本地增量文件
            if (syncSetting.CheckNewFiles)
            {
                List <string> cachedKeys = CachedHash.GetAllKeys(localHashDB);

                Dictionary <string, string> itemDict = CachedHash.GetAllItems(localHashDB);

                for (int i = 0; i < originalCount; ++i)
                {
                    if (skip[i])
                    {
                        continue;
                    }

                    string f = files[i];
                    if (itemDict.ContainsKey(f))
                    {
                        string oldHash = itemDict[f];
                        string newHash = Qiniu.Util.QETag.hash(f);
                        if (string.Equals(oldHash, newHash))
                        {
                            addFileExistsLog(string.Format("{0}\t{1}\t{2}", this.syncSetting.TargetBucket, files[i], keys[i]));
                            updateUploadLog("本地检查已同步,跳过文件 " + files[i]);
                            skip[i] = true;
                        }
                    }
                }
            }

            // 检查云端同名文件
            Qiniu.Util.Mac mac        = new Qiniu.Util.Mac(SystemConfig.ACCESS_KEY, SystemConfig.SECRET_KEY);
            string[]       remoteHash = BucketFileHash.BatchStat(mac, syncSetting.TargetBucket, keys);

            // 跳过
            if (!syncSetting.OverwriteDuplicate)
            {
                for (int i = 0; i < originalCount; ++i)
                {
                    if (skip[i])
                    {
                        continue;
                    }

                    if (!string.IsNullOrEmpty(remoteHash[i]))
                    {
                        string localHash = Qiniu.Util.QETag.hash(files[i]);
                        if (string.Equals(localHash, remoteHash[i]))
                        {
                            addFileNotOverwriteLog(string.Format("{0}\t{1}\t{2}", this.syncSetting.TargetBucket, files[i], keys[i]));
                            updateUploadLog("空间已存在相同文件,跳过文件 " + files[i]);
                            skip[i] = true;
                        }
                    }
                }
            }
            else // 覆盖
            {
                for (int i = 0; i < originalCount; ++i)
                {
                    if (skip[i])
                    {
                        continue;
                    }

                    if (!string.IsNullOrEmpty(remoteHash[i]))
                    {
                        string localHash = Qiniu.Util.QETag.hash(files[i]);
                        if (string.Equals(localHash, remoteHash[i]))
                        {
                            addFileNotOverwriteLog(string.Format("{0}\t{1}\t{2}", this.syncSetting.TargetBucket, files[i], keys[i]));
                            updateUploadLog("空间已存在相同文件,跳过文件 " + files[i]);
                            overwriteDict[files[i]] = true;
                        }
                    }
                }
            }

            using (StreamWriter sw = new StreamWriter(cacheFilePathDone))
            {
                for (int i = 0; i < files.Count; ++i)
                {
                    if (!skip[i])
                    {
                        sw.WriteLine(files[i]);
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// 1.根据设定参数进行必要的配置
        /// 2.检查过滤之后,生成待上传的文件列表并展示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonCheckFilesToUpload_Click(object sender, RoutedEventArgs e)
        {
            #region CHECK_SYNC_SETTINS

            // 检查并设置AK&SK
            if (string.IsNullOrEmpty(this.account.AccessKey) || string.IsNullOrEmpty(this.account.SecretKey))
            {
                this.SettingsErrorTextBlock.Text = "请设置AK&SK";
                return;
            }

            SystemConfig.ACCESS_KEY = this.account.AccessKey;
            SystemConfig.SECRET_KEY = this.account.SecretKey;

            // 检查本地同步目录与远程同步空间
            string syncDirectory = this.SyncLocalFolderTextBox.Text.Trim();
            if (string.IsNullOrEmpty(syncDirectory) || !Directory.Exists(syncDirectory))
            {
                this.SettingsErrorTextBlock.Text = "请设置本地待同步的目录";
                return;
            }
            if (this.SyncTargetBucketsComboBox.SelectedIndex < 0)
            {
                this.SettingsErrorTextBlock.Text = "请设置目标空间";
                return;
            }

            string targetBucket = this.SyncTargetBucketsComboBox.SelectedItem.ToString();

            if (this.syncSetting == null)
            {
                this.syncSetting = new SyncSetting();
            }

            this.syncSetting.LocalDirectory       = syncDirectory;
            this.syncSetting.TargetBucket         = targetBucket;
            this.syncSetting.SyncPrefix           = this.PrefixTextBox.Text.Trim();
            this.syncSetting.SkipPrefixes         = this.SkipPrefixesTextBox.Text.Trim();
            this.syncSetting.SkipSuffixes         = this.SkipSuffixesTextBox.Text.Trim();
            this.syncSetting.CheckNewFiles        = this.CheckNewFilesCheckBox.IsChecked.Value;
            this.syncSetting.UseShortFilename     = this.CheckBoxUseShortFilename.IsChecked.Value;
            this.syncSetting.OverwriteDuplicate   = this.RadioButtonOverwriteDuplicate.IsChecked.Value;
            this.syncSetting.SyncThreadCount      = (int)this.ThreadCountSlider.Value;
            this.syncSetting.ChunkUploadThreshold = (int)this.ChunkUploadThresholdSlider.Value * 1024 * 1024;
            this.syncSetting.DefaultChunkSize     = this.defaultChunkSize;
            this.syncSetting.UploadFromCDN        = this.RadioButtonFromCDN.IsChecked.Value;

            #endregion CHECK_SYNC_SETTINS

            #region SIMULATION

            StatResult statResult = this.bucketManager.stat(this.syncSetting.TargetBucket, "NONE_EXIST_KEY");

            if (statResult.ResponseInfo.isNetworkBroken())
            {
                this.SettingsErrorTextBlock.Text = "网络故障";
                return;
            }

            if (statResult.ResponseInfo.StatusCode == 401)
            {
                //ak & sk not right
                this.SettingsErrorTextBlock.Text = "AK 或 SK 不正确";
                return;
            }
            else if (statResult.ResponseInfo.StatusCode == 631)
            {
                //bucket not exist
                this.SettingsErrorTextBlock.Text = "指定空间不存在";
                return;
            }
            else if (statResult.ResponseInfo.StatusCode == 612 ||
                     statResult.ResponseInfo.StatusCode == 200)
            {
                //file exists or not
                //ignore
            }
            else if (statResult.ResponseInfo.StatusCode == 400)
            {
                if (string.IsNullOrEmpty(statResult.ResponseInfo.Error))
                {
                    this.SettingsErrorTextBlock.Text = "未知错误(状态代码400)";
                }
                else
                {
                    if (statResult.ResponseInfo.Error.Equals("incorrect zone"))
                    {
                        this.SettingsErrorTextBlock.Text = "上传入口机房设置错误";
                    }
                    else
                    {
                        this.SettingsErrorTextBlock.Text = statResult.ResponseInfo.Error;
                    }
                }
                return;
            }
            else
            {
                this.SettingsErrorTextBlock.Text = "未知错误,请联系七牛";
                Log.Error(string.Format("get buckets unknown error, {0}:{1}:{2}:{3}", statResult.ResponseInfo.StatusCode,
                                        statResult.ResponseInfo.Error, statResult.ResponseInfo.ReqId, statResult.Response));
                return;
            }

            #endregion SIMULATION

            int numFiles  = 0; // 总文件数
            int numUpload = 0; // 待上传文件数
            uploadItems.Clear();
            this.FilesToUploadDataGrid.DataContext = null;

            List <string> localFiles   = new List <string>(); // 本地待上传的文件
            List <string> saveKeys     = new List <string>(); // 保存到空间文件名
            List <string> fileEtags    = new List <string>(); // 待上传文件的ETAG
            List <long>   lastModified = new List <long>();   // 文件最后修改时间
            List <bool>   fileSkip     = new List <bool>();   // 是否跳过该文件(不上传)

            long T0 = (TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0))).Ticks;

            #region TRAVERSE_LOCAL_DIRECTORY

            DirectoryInfo di  = new DirectoryInfo(syncDirectory);
            FileInfo[]    ffi = di.GetFiles("*.*", SearchOption.AllDirectories);
            numFiles = ffi.Length;

            string savePrefix = this.PrefixTextBox.Text.Trim();

            if (this.syncSetting.UseShortFilename)
            {
                foreach (var fi in ffi)
                {
                    localFiles.Add(fi.FullName);
                    saveKeys.Add(savePrefix + fi.Name);
                    fileEtags.Add("_");
                    lastModified.Add((fi.LastWriteTime.Ticks - T0) / 10000);
                    fileSkip.Add(false);
                }
            }
            else
            {
                foreach (var fi in ffi)
                {
                    localFiles.Add(fi.FullName);
                    saveKeys.Add(savePrefix + fi.FullName);
                    fileEtags.Add("_");
                    lastModified.Add((fi.LastWriteTime.Ticks - T0) / 10000);
                    fileSkip.Add(false);
                }
            }

            #endregion TRAVERSE_LOCAL_DIRECTORY

            #region CHECK_PREFIX_SUFFX

            string skipPrefixes = this.SkipPrefixesTextBox.Text.Trim();
            string skipSuffixes = this.SkipSuffixesTextBox.Text.Trim();

            for (int i = 0; i < numFiles; ++i)
            {
                string saveKey = saveKeys[i];

                string[] ssPrfx = skipPrefixes.Split(',');
                foreach (string prefix in ssPrfx)
                {
                    if (!string.IsNullOrWhiteSpace(prefix))
                    {
                        if (saveKey.StartsWith(prefix.Trim()))
                        {
                            fileSkip[i] = true;
                            break;
                        }
                    }
                }

                string[] ssSufx = skipSuffixes.Split(',');
                foreach (string suffix in ssSufx)
                {
                    if (!string.IsNullOrWhiteSpace(suffix))
                    {
                        if (saveKey.EndsWith(suffix.Trim()))
                        {
                            fileSkip[i] = true;
                            break;
                        }
                    }
                }
            }
            #endregion CHECK_PREFIX_SUFFX

            string hashDBFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "qsunsync", "local_hash.db");
            if (!File.Exists(hashDBFile))
            {
                CachedHash.CreateCachedHashDB(hashDBFile);
            }
            SQLiteConnection localHashDBConn = new SQLiteConnection(string.Format("data source = {0}", hashDBFile));
            localHashDBConn.Open();
            Dictionary <string, HashDBItem> localHashDict = CachedHash.GetAllItems(localHashDBConn);
            localHashDBConn.Close();

            #region CHECK_LOCAL_DUPLICATE

            if (this.syncSetting.CheckNewFiles)
            {
                for (int i = 0; i < numFiles; ++i)
                {
                    if (fileSkip[i])
                    {
                        continue;
                    }

                    string fileName = localFiles[i];

                    if (localHashDict.ContainsKey(fileName))
                    {
                        string oldEtag = localHashDict[fileName].FileHash;
                        string newEtag = QETag.hash(fileName);

                        if (string.Equals(oldEtag, newEtag))
                        {
                            fileSkip[i] = true;
                        }
                        else
                        {
                            fileEtags[i] = newEtag;
                        }
                    }
                    else
                    {
                        fileEtags[i] = QETag.hash(fileName);
                    }
                }
            }
            else
            {
                for (int i = 0; i < numFiles; ++i)
                {
                    if (fileSkip[i])
                    {
                        continue;
                    }
                    fileEtags[i] = QETag.hash(localFiles[i]);
                }
            }

            #endregion CHECK_LOCAL_DUPLICATE

            #region CHECK_REMOTE_DUPLICATES

            // 如果选择了“强制覆盖”,那么无需进行远程检查
            if (!this.syncSetting.OverwriteDuplicate)
            {
                List <string> remoteHash   = new List <string>();
                List <long>   remoteUpdate = new List <long>();

                try
                {
                    Mac mac = new Mac(this.account.AccessKey, this.account.SecretKey);
                    BucketFileHash.BatchStat(mac, targetBucket, saveKeys, fileSkip, ref remoteHash, ref remoteUpdate);

                    for (int i = 0, k = 0; i < numFiles; ++i)
                    {
                        if (fileSkip[i])
                        {
                            continue;
                        }

                        if (string.Equals(fileEtags[i], remoteHash[k]))
                        {
                            // 云端已存在相同文件,跳过
                            fileSkip[i] = true;
                        }

                        ++k;
                    }
                }
                catch (Exception ex)
                {
                    this.SettingsErrorTextBlock.Text = ex.Message;
                    Log.Error(ex.Message);
                }
            }

            #endregion CHECK_REMOTE_DUPLICATES

            #region SHOW_UPLOAD_DETAILS

            this.SyncSettingTabControl.SelectedItem = this.TabItemFilesToUploadDetail;

            numUpload = numFiles;

            foreach (var b in fileSkip)
            {
                if (b)
                {
                    --numUpload;
                }
            }

            if (numUpload < 1)
            {
                TextBlockFilesToUploadSummery.Text = "没有待上传的文件";
                return;
            }


            double N = 0;

            for (int i = 0; i < numFiles; ++i)
            {
                if (fileSkip[i])
                {
                    continue;
                }

                string fsize = "0";

                long   n = ffi[i].Length;
                double K = 1.0 * n / 1024.0;
                double M = 0.0;
                if (K > 1024.0)
                {
                    M     = K / 1024.0;
                    fsize = string.Format("{0:0.00}MB", M);
                }
                else if (K > 1.0)
                {
                    fsize = string.Format("{0:0.00}KB", K);
                }
                else
                {
                    fsize = string.Format("{0}B", n);
                }

                N += n;

                uploadItems.Add(new UploadItem()
                {
                    LocalFile  = localFiles[i],
                    SaveKey    = saveKeys[i],
                    FileSize   = fsize,
                    FileHash   = fileEtags[i],
                    LastUpdate = lastModified[i].ToString()
                });
            }

            string vol  = "";
            double mega = 1024.0 * 1024;
            double kilo = 1024.0;
            if (N > mega)
            {
                vol = string.Format("{0:0.00}MB", N / mega);
            }
            else if (N > kilo)
            {
                vol = string.Format("{0:0.00}KB", N / kilo);
            }
            else
            {
                vol = string.Format("{0}B", N);
            }

            TextBlockFilesToUploadSummery.Text = string.Format("待上传的文件总数:{0}, 总大小:{1}", numUpload, vol);

            Dispatcher.Invoke(new Action(delegate
            {
                ObservableCollection <UploadItem> dataSource = new ObservableCollection <UploadItem>();
                foreach (var d in uploadItems)
                {
                    dataSource.Add(d);
                }
                this.FilesToUploadDataGrid.DataContext = dataSource;
            }));

            ButtonStartSync.IsEnabled = true;

            #endregion SHOW_UPLOAD_DETAILS
        }