问题描述
我需要从 REST API 调用中获取 jpeg 图像.我使用 XMLHttpRequest,因为请求需要身份验证标头(即,我不能只创建图像并将源设置为使用 user:passwd@url 的 URL).
I need to fetch a jpeg image from a REST API call. I use XMLHttpRequest as the request requires authentication headers (i.e. I can't just create an Image and set the source to the URL with user:passwd@url).
我认为我可以通过将 REST 数据设置为 CanvasImageData 对象来使用 Canvas 并调用 drawImage.但是,它不会绘制任何东西,也不会产生错误.REST 调用返回 Content-Type: image/jpeg 和 Transfer-Encoding: chunked.
I thought I'd be able to use a Canvas and call drawImage by setting the REST data to a CanvasImageData object. However, it doesn't draw anything, nor does it produce an error. The REST call returns Content-Type: image/jpeg and the Transfer-Encoding: chunked.
这种方法应该有效,还是我错过了其他东西?有更好的建议吗?
Should this approach work, or am I missing something else? Any better suggestions?
// map_request.imageBytes is a property that holds the binary response from the REST query
Canvas {
id: location_map
width: 2400
height: 1500
contextType: '2d'
onPaint: {
if (context && map_request.imageBytes)
{
var cid = context.createImageData(width, height);
cid.data = map_request.imageBytes;
context.drawImage(cid, 0, 0);
}
}
推荐答案
正确的解决方案是按照@folibis 的指示创建一个QQuickImageProvider.但是,由于我使用的是 Qt5.5,因此无法制作 QQuickAsyncImageProvider(在 Qt5.6 中引入).相反,您必须在将 QQuickImageProvider 构造为 QQmlImageProviderBase::ForceAsynchronousImageLoading 时设置 Flags.此标志确保调用 requestImage 不会阻塞主 GUI 线程.
The proper solution is to create a QQuickImageProvider as @folibis instructed. However, since I am using Qt5.5, I can't make a QQuickAsyncImageProvider (which is introduced in Qt5.6). Instead, you have to set the Flags when constructing the QQuickImageProvider to QQmlImageProviderBase::ForceAsynchronousImageLoading. This flag ensures that calling requestImage doesn't block the main GUI thread.
但是,requestImage 期望图像被返回,这导致在不阻塞该线程的情况下从网络获取图像数据的挑战.QNetworkAccessManager 用信号返回其状态,而 QQuickImageProvider 不是 QObject,所以我创建了一个辅助类来监控 QNetworkReply 的信号.
However, requestImage expects the Image to be returned, causing a challenge to fetch the Image data from the network without blocking that thread. QNetworkAccessManager returns its status with signals, and QQuickImageProvider isn't a QObject, so I made a helper class to monitor the signals for the QNetworkReply.
class ReplyMonitor : public QObject
{
Q_OBJECT
public:
ReplyMonitor(QNetworkAccessManager *);
public Q_SLOTS:
void handleReplyFinished();
void handleSslErrors(QNetworkReply *, const QList<QSslError> &);
void handleAuthenticationRequired(QNetworkReply *, QAuthenticator *);
public:
bool finished;
};
和
ReplyMonitor::ReplyMonitor(QNetworkAccessManager *mgr)
: finished(false)
{
connect(mgr, SIGNAL( finished(QNetworkReply *) ), this, SLOT( handleReplyFinished() ));
connect(mgr, SIGNAL( sslErrors(QNetworkReply *, const QList<QSslError> &) ),
this, SLOT( handleSslErrors(QNetworkReply*, const QList<QSslError> &) ));
connect(mgr, SIGNAL( authenticationRequired(QNetworkReply *, QAuthenticator *) ),
this, SLOT( handleAuthenticationRequired(QNetworkReply*, QAuthenticator*) ));
}
void ReplyMonitor::handleReplyFinished()
{
finished = true;
}
然后在 requestImage()
我检查 finished
并调用
Then in requestImage()
I check finished
and call
while (!monitor->finished)
{
QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
}
在我创建要返回的图像之前
before I create the Image to return with
if (reply->error() == QNetworkReply::NoError)
{
image.loadFromData(reply->readAll());
}
我省略了创建 QNetworkRequest 的细节,因为这是有据可查的.
I omitted the details of creating a QNetworkRequest, as that is well-documented.
这篇关于根据对 XmlHttpRequest (REST) 的响应在 QML 中显示图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!