1package archiver 2 3import ( 4 "fmt" 5 "io" 6 "log" 7 "net/http" 8 "os" 9 "strconv" 10) 11 12// The simplest use of this package: create an archive file 13// from a list of filenames. This is the recommended way to 14// do so using a default configuration, as it guarantees 15// the file format matches the file extension, because the 16// format to write is determined by the given extension. 17func ExampleArchive() { 18 // any files in this list are added 19 // to the top level of the archive; 20 // directories are recursively added 21 files := []string{ 22 "index.html", 23 "photo.jpg", 24 "blog", // directory 25 "/home/website/copyright.txt", 26 } 27 28 // archive format is determined by file extension 29 err := Archive(files, "blog_site.zip") 30 if err != nil { 31 log.Fatal(err) 32 } 33} 34 35// The simplest use of this package: extract all of an archive's 36// contents to a folder on disk using the default configuration. 37// The archive format is determined automatically. 38func ExampleUnarchive() { 39 err := Unarchive("blog_site.zip", "extracted/mysite") 40 if err != nil { 41 log.Fatal(err) 42 } 43} 44 45// In this example, the DefaultZip is being customized so that 46// all calls to its methods will use that configuration. 47func ExampleZip_default() { 48 DefaultZip.OverwriteExisting = true 49 DefaultZip.ImplicitTopLevelFolder = true 50 // any subsequent use of DefaultZip uses 51 // this modified configuration 52} 53 54// Here we create our own instance of the Zip format. No need 55// to use the constructor function (NewZip) or the default 56// instance (DefaultZip) if we do not want to. Instantiating 57// the type like this allows us to easily be very explicit 58// about our configuration. 59func ExampleZip_custom() { 60 z := &Zip{ 61 CompressionLevel: 3, 62 OverwriteExisting: false, 63 MkdirAll: true, 64 SelectiveCompression: true, 65 ImplicitTopLevelFolder: true, 66 ContinueOnError: false, 67 } 68 // z is now ready to use for whatever (this is a dumb example) 69 fmt.Println(z.CheckExt("test.zip")) 70} 71 72// Much like the package-level Archive function, this creates an 73// archive using the configuration of the Zip instance it is called 74// on. The output filename must match the format's recognized file 75// extension(s). 76func ExampleZip_Archive() { 77 err := DefaultZip.Archive([]string{"..."}, "example.zip") 78 if err != nil { 79 log.Fatal(err) 80 } 81} 82 83// It's easy to list the items in an archive. This example 84// prints the name and size of each file in the archive. Like 85// other top-level functions in this package, the format is 86// inferred automatically for you. 87func ExampleWalk() { 88 err := Walk("example.tar.gz", func(f File) error { 89 fmt.Println(f.Name(), f.Size()) 90 // you could also read the contents; f is an io.Reader! 91 return nil 92 }) 93 if err != nil { 94 log.Fatal(err) 95 } 96} 97 98// This example extracts target.txt from inside example.rar 99// and puts it into a folder on disk called output/dir. 100func ExampleExtract() { 101 err := Extract("example.rar", "target.txt", "output/dir") 102 if err != nil { 103 log.Fatal(err) 104 } 105} 106 107// This example demonstrates how to read an 108// archive in a streaming fashion. The idea 109// is that you can stream the bytes of an 110// archive from a stream, regardless of 111// whether it is an actual file on disk. 112// This means that you can read a huge 113// archive file-by-file rather than having 114// to store it all on disk first. In this 115// example, we read a hypothetical archive 116// from a (fake) HTTP request body and 117// print its file names and sizes. The 118// files can be read, of course, but they 119// do not have to be. 120func ExampleZip_streamingRead() { 121 // for the sake of the example compiling, pretend we have an HTTP request 122 req := new(http.Request) 123 contentLen, err := strconv.Atoi(req.Header.Get("Content-Length")) 124 if err != nil { 125 log.Fatal(err) 126 } 127 128 // the Zip format requires knowing the length of the stream, 129 // but other formats don't generally require it, so it 130 // could be left as 0 when using those 131 err = DefaultZip.Open(req.Body, int64(contentLen)) 132 if err != nil { 133 log.Fatal(err) 134 } 135 defer DefaultZip.Close() 136 137 // Note that DefaultZip now contains some state that 138 // is critical to reading the stream until it is closed, 139 // so do not reuse it until then. 140 141 // iterate each file in the archive until EOF 142 for { 143 f, err := DefaultZip.Read() 144 if err == io.EOF { 145 break 146 } 147 if err != nil { 148 log.Fatal(err) 149 } 150 151 // f is an io.ReadCloser, so you can read its contents 152 // if you wish; or you can access its header info through 153 // f.Header or the embedded os.FileInfo 154 fmt.Println("File name:", f.Name(), "File size:", f.Size()) 155 156 // be sure to close f before moving on!! 157 err = f.Close() 158 if err != nil { 159 log.Fatal(err) 160 } 161 } 162} 163 164// This example demonstrates how to write an 165// archive in a streaming fashion. The idea 166// is that you can stream the bytes of a new 167// archive that is created on-the-fly from 168// generic streams. Those streams could be 169// actual files on disk, or they could be over 170// a network, or standard output, or any other 171// io.Reader/io.Writer. This example only adds 172// one file to the archive and writes the 173// resulting archive to standard output, but you 174// could add as many files as needed with a loop. 175func ExampleZip_streamingWrite() { 176 err := DefaultZip.Create(os.Stdout) 177 if err != nil { 178 log.Fatal(err) 179 } 180 defer DefaultZip.Close() 181 182 // Note that DefaultZip now contains state 183 // critical to a successful write until it 184 // is closed, so don't reuse it for anything 185 // else until then. 186 187 // At this point, you can open an actual file 188 // to add to the archive, or the "file" could 189 // come from any io.ReadCloser stream. If you 190 // only have an io.Reader, you can use 191 // ReadFakeCloser to make it into an 192 // io.ReadCloser. 193 194 // The next part is a little tricky if you 195 // don't have an actual file because you will 196 // need an os.FileInfo. Fortunately, that's an 197 // interface! So go ahead and implement it in 198 // whatever way makes the most sense to you. 199 // You'll also need to give the file a name 200 // for within the archive. In this example, 201 // we'll open a real file. 202 203 file, err := os.Open("foo.txt") 204 if err != nil { 205 log.Fatal(err) 206 } 207 defer file.Close() 208 fileInfo, err := file.Stat() 209 if err != nil { 210 log.Fatal(err) 211 } 212 213 err = DefaultZip.Write(File{ 214 FileInfo: FileInfo{ 215 FileInfo: fileInfo, 216 CustomName: "name/in/archive.txt", 217 }, 218 ReadCloser: file, // does not have to be an actual file 219 }) 220 if err != nil { 221 log.Fatal(err) 222 } 223} 224 225// This example compresses a standard tar file into a tar.gz file. 226// Compression formats are selected by file extension. 227func ExampleCompressFile() { 228 err := CompressFile("example.tar", "example.tar.gz") 229 if err != nil { 230 log.Fatal(err) 231 } 232} 233 234// This example changes the default configuration for 235// the Gz compression format. 236func ExampleCompressFile_custom() { 237 DefaultGz.CompressionLevel = 5 238 // any calls to DefaultGz now use the modified configuration 239} 240 241// This example creates a new Gz instance and 242// uses it to compress a stream, writing to 243// another stream. This is sometimes preferable 244// over modifying the DefaultGz. 245func ExampleGz_Compress_custom() { 246 gz := &Gz{CompressionLevel: 5} 247 err := gz.Compress(os.Stdin, os.Stdout) 248 if err != nil { 249 log.Fatal(err) 250 } 251} 252 253// This example decompresses a gzipped tarball and writes 254// it to an adjacent file. 255func ExampleDecompressFile() { 256 err := DecompressFile("example.tar.gz", "example.tar") 257 if err != nil { 258 log.Fatal(err) 259 } 260} 261