Close finishes writing the zip file by writing the central directory. It does not close the underlying writer.
()
| 76 | // Close finishes writing the zip file by writing the central directory. |
| 77 | // It does not close the underlying writer. |
| 78 | func (w *Writer) Close() error { |
| 79 | if w.last != nil && !w.last.closed { |
| 80 | if err := w.last.close(); err != nil { |
| 81 | return err |
| 82 | } |
| 83 | w.last = nil |
| 84 | } |
| 85 | if w.closed { |
| 86 | return errors.New("zip: writer closed twice") |
| 87 | } |
| 88 | w.closed = true |
| 89 | |
| 90 | // write central directory |
| 91 | start := w.cw.count |
| 92 | for _, h := range w.dir { |
| 93 | var buf [directoryHeaderLen]byte |
| 94 | b := writeBuf(buf[:]) |
| 95 | b.uint32(uint32(directoryHeaderSignature)) |
| 96 | b.uint16(h.CreatorVersion) |
| 97 | b.uint16(h.ReaderVersion) |
| 98 | b.uint16(h.Flags) |
| 99 | b.uint16(h.Method) |
| 100 | b.uint16(h.ModifiedTime) |
| 101 | b.uint16(h.ModifiedDate) |
| 102 | b.uint32(h.CRC32) |
| 103 | if h.isZip64() || h.offset >= uint32max { |
| 104 | // the file needs a zip64 header. store maxint in both |
| 105 | // 32 bit size fields (and offset later) to signal that the |
| 106 | // zip64 extra header should be used. |
| 107 | b.uint32(uint32max) // compressed size |
| 108 | b.uint32(uint32max) // uncompressed size |
| 109 | |
| 110 | // append a zip64 extra block to Extra |
| 111 | var buf [28]byte // 2x uint16 + 3x uint64 |
| 112 | eb := writeBuf(buf[:]) |
| 113 | eb.uint16(zip64ExtraID) |
| 114 | eb.uint16(24) // size = 3x uint64 |
| 115 | eb.uint64(h.UncompressedSize64) |
| 116 | eb.uint64(h.CompressedSize64) |
| 117 | eb.uint64(h.offset) |
| 118 | h.Extra = append(h.Extra, buf[:]...) |
| 119 | } else { |
| 120 | b.uint32(h.CompressedSize) |
| 121 | b.uint32(h.UncompressedSize) |
| 122 | } |
| 123 | |
| 124 | b.uint16(uint16(len(h.Name))) |
| 125 | b.uint16(uint16(len(h.Extra))) |
| 126 | b.uint16(uint16(len(h.Comment))) |
| 127 | b = b[4:] // skip disk number start and internal file attr (2x uint16) |
| 128 | b.uint32(h.ExternalAttrs) |
| 129 | if h.offset > uint32max { |
| 130 | b.uint32(uint32max) |
| 131 | } else { |
| 132 | b.uint32(uint32(h.offset)) |
| 133 | } |
| 134 | if _, err := w.cw.Write(buf[:]); err != nil { |
| 135 | return err |