question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Possible to get 'total bytes sent' and 'stream end' from ctx.seekableStream ?

See original GitHub issue

I’m using ctx.seekableStream(file.inputStream(), "audio/mpeg") to stream files to the client and I’m planning to log some statistics about how many bytes have actually been sent. As far as I understand the browser it will call the endpoint multiple times to get a small chunk on every request. Is it possible to get this information from the seekable stream somehow? And is it possible to identify when the stream (chunk) ended?

Ty for any information.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:14 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
tipsycommented, Feb 4, 2022

Nice ! I’ll add an “info” tag to the issue 😃

0reactions
fq-selbachcommented, Feb 2, 2022

I think I solved the “mystery” 🙂.

CountingInputStream counts the skipped bytes as well meaning each request that reads only a chunk of the file is counted as “read bytes” + “skipped bytes” to find position. In the case where the whole file was read at once I was simply counting the bytes too early since the stream is read after ctx.result(inputStream) returned.

So I ended up writing a new CountingInputStream implementation instead of a new SeekableWriter like this:

import static org.apache.commons.io.IOUtils.EOF;
import java.io.IOException;
import java.io.InputStream;
import java.util.function.Consumer;
import org.apache.commons.io.input.CountingInputStream;

/**
 * Adapted version of {@link CountingInputStream} to get download statistics.
 */
public class DownloadCounterStream extends CountingInputStream {
	
    private long totalBytesRead = 0l;
    private Consumer<Long> onClose;
    
    /**
    * Constructs a new DownloadCounterStream.
    * @param in - the input stream
    * @param onClose - callback on stream close with totalBytesRead
    */
    public DownloadCounterStream(final InputStream in, Consumer<Long> onClose) {
        super(in);
        this.onClose = onClose;
    }
    
    /**
     * Get total bytes actually read by this stream 
     * (without skipped bytes like {@link #getByteCount()}).
     */
    public long getTotalBytesRead(){
    	return this.totalBytesRead;
    }
    
    /**
     * Adds the number of read bytes to the count.
     */
    @Override
    protected synchronized void afterRead(final int n) {
        if (n != EOF) {
            this.totalBytesRead += n;
        }
        super.afterRead(n);
    }
    
    @Override 
    public void close() throws IOException {
    	super.close();
    	this.onClose.accept(this.totalBytesRead);
    }
}

And I’m using it like this:

DownloadCounterStream is = new DownloadCounterStream(Files.newInputStream(file.toPath()), total -> {
    System.out.println("Total bytes sent: " + total);
});
ctx.seekableStream(is, ct);
Read more comments on GitHub >

github_iconTop Results From Across the Web

Possible to get 'total bytes sent' and 'stream end' from ctx. ...
I'm using ctx.seekableStream(file.inputStream(), "audio/mpeg") to stream files to the client and I'm planning to log some statistics about how many bytes ...
Read more >
How to get total bytes transferred by stream?
I need to collect statistics of usage and total bytes send and received by server. I suppose, in MediaEventListener.onStop() should be some ...
Read more >
Java Advanced Imaging: Class SeekableStream
An attempt is made to read as many as len bytes, but a smaller number may be read, possibly zero. The number of...
Read more >
Archive - v3 documentation
seekableStream (resultStream) // set a stream that will be sent to the client in byte ranges ctx.contentType(contentType) // set the response content type ......
Read more >
How to correctly calculate the the number of bytes ...
Alright, I made something that essentially is a passthrough, but calls a callback with data as it comes in: // creates a stream...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found