2

我正在编写一个服务器,它将压缩文件并通过 http 套接字发送它们。

不幸的是,它们并不是真正的文件,它们更像是来自远程源的数据库条目。

我想压缩内存中的每个条目,然后通过我的 http 服务器将它们发送出去,每个条目都可能很大,比如每个 1GB。

我以块的形式从源接收数据,例如 16mb(但可以是任何有意义的块大小)。

从概念上讲,这就是正在发生的事情,尽管这是一些伪代码:

archive *_archive = archive_write_new();

//set to zip format
bool ok = true;
ok |= archive_write_set_format( _archive, ARCHIVE_FORMAT_ZIP );
ok |= archive_write_add_filter( _archive, ARCHIVE_FILTER_NONE );

char *_archiveBuffer = malloc(8192);
size_t _used;
ok = archive_write_open_memory( _archive, _archiveBuffer, 8192, &_used );

if (!ok) return ERROR;

archive_entry *_archiveEntry = archive_entry_new();

//fetch metadata about the object by id
QString id = "123456789";
QJsonObject metadata = database.fetchMetadata(id);
int size = metadata["size"].toInt();

//write the http header
httpd.writeHeader(size);

archive_entry_set_pathname( _archiveEntry, "entries/"+id );
archive_entry_set_size( entry, size );
archive_entry_set_filetype( _archiveEntry, AE_IFREG );
//archive_entry_set_perm( entry, ... );

archive_write_header( _archive, _archiveEntry );

int chunksize = 16777216;
for (int w = 0; w < size; w+=chunksize)
{
    QByteArray chunk = database.fetchChunk(id,chunksize);
    archive_write_data( _archive, chunk.data(), (size_t) chunk.size() );

    //accumulate data, then fetch compressed data from _archiveBuffer and write to httpd
    if (_used > 0)
    {
        httpd.writeData(_archiveBuffer);
        //clear archive buffer?
    }
}

archive_entry_free(_archiveEntry);
archive_write_close(_archive);

httpd.writeData(_archiveBuffer);

archive_write_free(_archive);

问题是,我如何知道数据何时被压缩到 _archiveBuffer,何时压缩,如何读取缓冲区然后清除它,重置 _used 计数器。我假设如果_used>0发生了压缩/刷新。

另外,_archiveBuffer 是否需要大于我的块大小?

似乎我可能需要使用回调,但不清楚如何将 archive_write_open 与回调和内存缓冲区一起使用。

我似乎无法在网上找到示例。

任何帮助,将不胜感激!

4

1 回答 1

1

解决方案比我想象的要容易得多……只花了一分钟就意识到了。

我相信这对于那些熟悉库和流的人来说是显而易见的。

使用回调就是答案。不要关心在内存中打开,因为这会创建一个无用的额外层,因为库已经自行管理。

根据多线程的配置方式,当归档流上发生有趣的事情时,回调将执行,例如,您可以一遍又一遍地将单个字节写入归档,但只有当它饱和时才会发生回调。那时你可以写信到网络或回调中的任何地方。所以这void *client_data是关键,因为它链接回您的主要类和 API。

就我而言,在(存档)数据可用之前,我不想编写 http 标头,因为在获取时可能会发生任何错误,这可能会导致不同的 http 标头。

当数据完成后,closeandfree函数也将使用回调来完成它们的工作,因此需要在这些回调完成后发生析构函数。

现在的任务是对这些请求进行多线程处理......现在我得到了库,这似乎很简单。

如果有人感兴趣,我可以发布新的伪代码。

于 2019-11-25T04:55:08.690 回答