31
loading...
This website collects cookies to deliver better user experience
This post is originally published on yoursunny.com blog https://yoursunny.com/t/2021/das-stream-bits/
0
bits, the number of 1
bits.https://summer-host-storage.yoursunny.dev/6705fb/18fa05/%E2%98%80%EF%B8%8F.bin
^ ^ ^
zeros ones filename
(in hexadecimal) (URI encoded)
0
bits and 1
bits from the URI, and reconstruct the sorted file accordingly.0
bits and 1
bits in a file, how to generate a file with those bits?"0"
and "1"
repeated for requested length.def makeFileFromBitCounts(filename: str, cnt0: int, cnt1: int) -> None:
bitString = '0' * cnt0 + '1' * cnt1
byteCount = (cnt0 + cnt1) // 8
arrayOfBytes = int(bitString, base=2).to_bytes(byteCount, byteorder='big')
with open(filename, mode='wb') as f:
f.write(arrayOfBytes)
void
streamFileFromBitCounts(std::ostream& os, size_t cnt0, size_t cnt1)
{
assert((cnt0 + cnt1) % 8 == 0);
size_t bytes0 = cnt0 / 8;
size_t bytes1 = cnt1 / 8;
std::optional<uint8_t> middleByte;
size_t middle0 = cnt0 % 8;
size_t middle1 = cnt1 % 8;
if (middle0 + middle1 > 0) {
assert(middle0 + middle1 == 8);
middleByte = 0xFF >> middle0;
}
for (size_t i = 0; i < bytes0; ++i) {
os.put(static_cast<uint8_t>(0x00));
}
if (middleByte.has_value()) {
os.put(middleByte.value());
}
for (size_t i = 0; i < bytes1; ++i) {
os.put(static_cast<uint8_t>(0xFF));
}
}
Blob
API and URL.createObjectURL() allow generating a downloadable file from JavaScript, the entire file must be allocated in memory.var (
buf0 = make([]byte, 1048576) // create 1MB page filled with 0x00 bytes
buf1 = bytes.Repeat([]byte{0xFF}, 1048576) // create 1MB page filled with 0xFF bytes
)
func handler(w http.ResponseWriter, req *http.Request) {
// parse URI and extract number of zeros and ones
var cnt0, cnt1 int
var name string
if _, e := fmt.Sscanf(req.URL.Path, "/%x/%x/%s", &cnt0, &cnt1, &name); e != nil {
w.WriteHeader(http.StatusNotFound)
return
}
// tell browser/client that:
// (1) the response is binary file, not text or HTML
// (2) the response is gzip compressed
// (3) browser should prompt for a download instead of display the file
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Encoding", "gzip")
w.Header().Set("Content-Disposition", "attachment")
// calculate number of 0x00 and 0xFF pages and leftover bytes, and the middle byte
bytes0, bytes1 := cnt0/8, cnt1/8
middle0, middle1 := cnt0%8, cnt1%8
pages0, pages1 := bytes0/len(buf0), bytes1/len(buf1)
bytes0 -= pages0 * len(buf0)
bytes1 -= pages1 * len(buf1)
z, _ := gzip.NewWriterLevel(w, 1) // make gzip compressor, fastest mode
defer z.Close() // close and flush when it's done
writePages := func(page []byte, count int) error { // subroutine to write some pages
ctx := req.Context()
for i := 0; i < count; i++ {
z.Write(page) // pipe one page to the gzip compressor
select {
case <-ctx.Done(): // client disconnected
return ctx.Err() // return non-nil error
case <-time.After(time.Millisecond): // delay 1ms and continue writing
}
}
return nil
}
if e := writePages(buf0, pages0); e != nil { // write 0x00 pages
return // stop if client has disconnected
}
z.Write(buf0[:bytes0]) // write leftover 0x00 bytes
if middle0+middle1 > 0 { // write the middle byte, if there is one
z.Write([]byte{0xFF >> middle0})
}
z.Write(buf1[:bytes1]) // write leftover 0xFF bytes
writePages(buf1, pages1) // write 0xFF pages
}
Accept-Encoding: gzip
header..dev
domain I'm using is designated as a "secure namespace" such that most browsers won't even connect to it over plain HTTP.Caddyfile
uses a reverse_proxy
directive to the HTTP server:https://summer-host-storage.yoursunny.dev {
reverse_proxy http://127.0.0.1:3333 {
flush_interval 1s
transport http {
compression off
}
}
}
Accept-Encoding: gzip
request header, and then decompress the response if the incoming request does not accept gzip compression.