public override void Execute() { AWSAuthConnection svc = new AWSAuthConnection(); IEnumerable<ListEntry> keys; if (!big) { if (key.EndsWith("*") || sub) { while (key.EndsWith("*")) key = key.Substring(0, key.Length - 1); IterativeList list = new IterativeList(bucket, key); if (list.Count == IterativeList.EntryCount.some && explicitFilename) throw new SyntaxException("You specified a destination filename but there is more than one key; can't copy multiple keys to one file"); keys = list; } else { List<ListEntry> singleton = new List<ListEntry>(); singleton.Add(new ListEntry(key, DateTime.UtcNow, null, 0, null, null)); keys = singleton; } } else { if (key.EndsWith("*")) throw new SyntaxException("Can't use wildcard (*) with the /big option"); else { List<ListEntry> sorted = new List<ListEntry>(); foreach (ListEntry e in new IterativeList(bucket, key + ".", new Regex("^" + Regex.Escape(key) + @"\.\d{3,5}$"))) sorted.Add(e); if (sorted.Count == 0) throw new FileNotFoundException("Not found: " + key + ".000"); sorted.Sort(NumericSuffixCompare); keys = sorted; } } if (keys is IterativeList && (keys as IterativeList).Count == IterativeList.EntryCount.zero) throw new FileNotFoundException("No keys found: " + key); else { FileStream fs = null; ConsoleCancelEventHandler deletePartialFileHandler = delegate { if (fs != null) { try { fs.Close(); } catch { } File.Delete(fs.Name); Console.WriteLine("Deleted partial file: " + fs.Name); } }; Console.CancelKeyPress += deletePartialFileHandler; try { if (big) fs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite); int sequence = 0; foreach (ListEntry entry in keys) { GetResponse getResp = svc.get(bucket, entry.Key, null, true); if (!big) { string thisFilename; if (sub) { thisFilename = Path.Combine(filename, KeyToFilename(entry.Key.Substring(key.Length))); string directoryName = Path.GetDirectoryName(thisFilename); if (!Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName); } else if (explicitFilename) thisFilename = filename; else thisFilename = entry.Key.Substring(entry.Key.LastIndexOf("/") + 1); fs = new FileStream(thisFilename, FileMode.Create, FileAccess.ReadWrite); } else { if (!entry.Key.EndsWith(string.Format(".{0:000}", sequence))) { Console.Error.WriteLine(string.Format("Warning: The download has completed because there is no chunk number {0}, but there are chunks on S3 with higher numbers. These chunks were probably uploaded to S3 when the file was larger than it is now, but it could indicate a missing chunk. To surpress this message, delete the later chunks.", sequence)); break; } } Console.WriteLine(string.Format("{0}/{1}", bucket, entry.Key)); StreamToStream(getResp.Object.Stream, fs, getResp.Connection.Headers["ETag"], entry.Key, entry.Size); getResp.Object.Stream.Close(); if (!big) fs.Close(); getResp.Connection.Close(); sequence++; } if (big) fs.Close(); } catch { deletePartialFileHandler(null, null); throw; } finally { Console.CancelKeyPress -= deletePartialFileHandler; } } }
public override void Execute() { AWSAuthConnection svc = new AWSAuthConnection(); IEnumerable<ListEntry> keys; if (!big) { if (key.EndsWith("*") || sub) { while (key.EndsWith("*")) key = key.Substring(0, key.Length - 1); IterativeList list = new IterativeList(bucket, key, regex); if (list.Count == IterativeList.EntryCount.some && explicitFilename) throw new SyntaxException("You specified a destination filename but there is more than one key; can't copy multiple keys to one file"); keys = list; } else { List<ListEntry> singleton = new List<ListEntry>(); singleton.Add(new ListEntry(key, DateTime.UtcNow, null, 0, null, null)); keys = singleton; } } else { if (key.EndsWith("*")) throw new SyntaxException("Can't use wildcard (*) with the /big option"); else { List<ListEntry> sorted = new List<ListEntry>(); foreach (ListEntry e in new IterativeList(bucket, key + ".", new Regex("^" + Regex.Escape(key) + @"\.\d{3,5}$"))) sorted.Add(e); if (sorted.Count == 0) throw new FileNotFoundException("Not found: " + key + ".000"); sorted.Sort(NumericSuffixCompare); keys = sorted; } } if (keys is IterativeList && (keys as IterativeList).Count == IterativeList.EntryCount.zero) throw new FileNotFoundException("No keys found: " + key); else { FileStream fs = null; ConsoleCancelEventHandler deletePartialFileHandler = delegate { if (fs != null) { try { fs.Close(); } catch { } File.Delete(fs.Name); Console.Error.WriteLine("Deleted partial file: " + fs.Name); } }; Console.CancelKeyPress += deletePartialFileHandler; try { if (big) fs = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite); int sequence = 0; foreach (ListEntry entry in keys) { string thisFilename = null; DateTime thisLastModified = DateTime.MinValue; if (!big) { if (sub) { if ("*" == Path.GetFileNameWithoutExtension(filename)) { // replace star with key/prefix: // bucket/path/prefix/[files] c:\local\* /sub ==> c:\local\path\prefix\[files] thisFilename = Path.Combine(Path.GetDirectoryName(filename), KeyToFilename(entry.Key)); } else { // strip key/prefix, leaving only filename: // bucket/path/prefix/[files] c:\local\ /sub ==> c:\local\[files] thisFilename = Path.Combine(filename, KeyToFilename(entry.Key.Substring(key.Length))); } string directoryName = Path.GetDirectoryName(thisFilename); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } } else if (explicitFilename) { thisFilename = filename; } else { thisFilename = entry.Key.Substring(entry.Key.LastIndexOf("/") + 1); } if(Path.GetFileName (thisFilename).Trim ().Length == 0) { continue; } thisLastModified = File.GetLastWriteTimeUtc (thisFilename); fs = null; } else { if (!entry.Key.EndsWith(string.Format(".{0:000}", sequence))) { Console.Error.WriteLine(string.Format("Warning: The download has completed because there is no chunk number {0}, but there are chunks on S3 with higher numbers. These chunks were probably uploaded to S3 when the file was larger than it is now, but it could indicate a missing chunk. To surpress this message, delete the later chunks.", sequence)); break; } } Console.Write(string.Format("{0}/{1} {2} ", bucket, entry.Key, s3.Utils.FormatFileSize(entry.Size))); if (null != install) { install.SetFile(thisFilename, !File.Exists(thisFilename)); } try { GetResponse getResp = svc.getIfModifiedSince(bucket, entry.Key, thisLastModified, true); // may throw 304 if(fs == null) fs = new FileStream(thisFilename, FileMode.Create, FileAccess.ReadWrite); StreamToStream(getResp.Object.Stream, fs, md5 ? getResp.Connection.Headers["ETag"] : null, entry.Key, entry.Size); getResp.Object.Stream.Close(); if (!big) fs.Close(); getResp.Connection.Close(); sequence++; File.SetLastWriteTimeUtc (thisFilename, entry.LastModified); Console.WriteLine(); if (null != install) { // newer file downloaded install.SetFile(thisFilename, true); } } catch(WebException x) { if(x.Message.Contains ("(304)")) { Console.WriteLine(" Not modified"); continue; } throw; } } if (big) fs.Close(); if (null != install) { install.InstallProducts(true); } } catch { deletePartialFileHandler(null, null); throw; } finally { Console.CancelKeyPress -= deletePartialFileHandler; } } }