How to pass several parameters when uploading image to imgur - qt

I'm trying to make a function that uploads a picture to imgur and the function is working in the form below but differently then I was expecting.
bool ImgurUploader::upload( QImage image )
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
image.save(&buffer, "PNG");
QByteArray params;
params.append(byteArray.toBase64());
QNetworkRequest request;
request.setUrl(QUrl("https://api.imgur.com/3/image"));
request.setRawHeader("Content-Type", "application/application/x-www-form-urlencoded");
request.setRawHeader("Authorization", "Client-ID 16d41e28a3ba71e");
mAccessManager->post(request, params);
}
I was expecting and trying at first to pass the image param in form like this:
params.append("image=");
params.append(byteArray.toBase64());
But when I do I get an "400 Bad Request" and the error is "Invalid URL".
How can I send several params? Am I using the wrong approach?

You can have a look at their Android Upload Example.
If you look at the upload request here, you can see that parameters are not sent in the body of the POST request (as you are trying to do). Instead, they are queries that are appended to the URL (this can be done in Qt using QUrlQuery), the image is sent in the body of the request and there is no need to encode it using base64 (this is better as it can save some network traffic).
Here is how your upload function should look like:
bool ImgurUploader::upload(QImage image, QString title, QString description)
{
QByteArray byteArray;
QBuffer buffer(&byteArray);
image.save(&buffer, "PNG");
QUrlQuery urlQuery;
urlQuery.addQueryItem("title", title);
urlQuery.addQueryItem("description", description);
QNetworkRequest request;
QUrl url("https://api.imgur.com/3/image");
url.setQuery(urlQuery);
request.setUrl(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,
"application/application/x-www-form-urlencoded");
request.setRawHeader("Authorization", "Client-ID 16d41e28a3ba71e");
mAccessManager->post(request, byteArray);
}

Related

qt restapi post no response

I transfer data with "qt" over rest api on an nestJs service. the nestJs service work fine, but I don't receive any response in "qt".
here a snippet from qt:
QNetworkRequest request;
request.setUrl(myUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkAccessManager *restClient;
restClient = new QNetworkAccessManager();
QNetworkReply *replay = restClient->post(request, *payload);
QByteArray result = replay->readAll();
qDebug() << result;
the console print is always:
""
the correct response from my nestJs service is (received with insomnia rest client tool):
{
"Generated": {},
"ErrorCode": 200,
"ErrorText": "OK"
}
thanks for help.
Requests are asynchronous so you must use the finished signal:
QNetworkReply *replay = restClient->post(request, *payload);
QObject::connect(replay, &QNetworkReply::finished, [replay](){
QByteArray result = replay->readAll();
qDebug() << result;
replay->deleteLater();
});

Twitter api error "code 32 Could not authenticate you" when trying to upload images

I am trying to upload photos to twitter from my app and i am using https://github.com/pipacs/o2 library for OAuth.
The following is the code that i am using:
QFile file(imgPath);
if (!file.open(QIODevice::ReadOnly))
{
return false;
}
QByteArray m_buffer = file.readAll();
O1Requestor* requestor = new O1Requestor(d->netMngr, d->o1Twitter, this);
QList<O0RequestParameter> reqParams = QList<O0RequestParameter>();
reqParams << O0RequestParameter(QByteArray("media"), m_buffer);
reqParams << O0RequestParameter(QByteArray("media_type"), QByteArray("image/jpeg"));
QByteArray postData = O1::createQueryParameters(reqParams);
QUrl url = QUrl("https://upload.twitter.com/1.1/media/upload.json");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM);
QNetworkReply *reply = requestor->post(request, reqParams, postData);
The result is the following:
ERROR: "Host requires authentication"
Content: "{"errors":[{"code":32,"message":"Could not authenticate you."}]}"
I tried doing something simple like posting a tweet saying Hello to test the authentication using statuses/update endpoint and it worked with no errors.
The following is the code also if it is required:
QUrl url2 = QUrl("https://api.twitter.com/1.1/statuses/update.json);
reqParams = QList<O0RequestParameter>();
reqParams << O0RequestParameter(QByteArray("status"), "Hello");
postData = O1::createQueryParameters(reqParams);
request.setUrl(url2);
request.setHeader(QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM);
QNetworkReply *reply = requestor->post(request, reqParams, postData);
Could you please help me with this issue.
Thanks
Similar to this answer, you will need to ensure that the image content in m_buffer is sent as a base-64 encoded string. Otherwise, the Twitter API will return error 32.

QNetworkReply behavior againt local site with authentication

i'm using QNetworkReply in order to issue a simple GET request to my router interface. Basically if the post data is empty i issue a GET otherwise i will issue a POST. Let's stick with the GET
QString url=ui->lineEdit_url->text();
QString paras=ui->pTextEdit_paras->toPlainText();
qDebug()<< "paras" << paras;
QByteArray post_data;
post_data.append(paras);
QNetworkRequest request = QNetworkRequest(QUrl(url));
request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
if(post_data.isEmpty())
{
//nam->head(request);
nam->get(request);
}
else
{
nam->post(request,post_data);
}
now with
...
connect(nam,
SIGNAL(finished(QNetworkReply*)),
this,
SLOT(finished(QNetworkReply*)));
...
void HttppostWindow::finished(QNetworkReply *reply)
{
if(reply->error() == QNetworkReply::NoError)
{
ui->textEdit_result->setText(QObject::tr(reply->readAll()));
}
else
{
ui->textEdit_result->setPlainText(reply->errorString());
}
}
i show the answer in the ui.
Right now the local interface asks for a login and a pw. The problem is that the retrieved text with the GET command is the one that the interface would show if the user would have insterted a wrong password (autentication failed please try again and so on).
Moreover with the code nam->head(request) i should be able to retrieve the header, but the content of replyAll is empty.
Any ideas?
After nam->head(request) you don't need to use reply->readAll().
Instead of this you should use methods like:
QByteArray rawHeader(const QByteArray &headerName) const;
QList<QByteArray> rawHeaderList() const;
const QList<RawHeaderPair> &rawHeaderPairs() const;
With this methods you can view content of your head request.
Also your sample code has memory leak. You should delete the reply whis reply->deleteLater() inside your finished slot.

Get http code request

U use QNetworkRequest to send post request. How can I get HTTP code of request? I send some request to server, on server I can see my request, but i have to check http code which server will return to application.
QNetworkRequest can not be used without QNetworkAccessManager that's responsible for making the actual request to the web server. Each request done by QNetworkAccessManager instance returns QNetworkReply where you should look for the status code from the server. It's located inside the QNetworkReply instance headers.
The request is asynchronous so it can be catch when signal is triggered.
Easiest example would be:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
Then in the slot implementation:
void replyFinished(QNetworkReply *resp){
QVariant status_code = resp->attribute(QNetworkRequest::HttpStatusCodeAttribute);
status_code.is_valid(){
// Print or catch the status code
QString status = status_code.toString(); // or status_code.toInt();
qDebug() << status;
}
}
Have a look on the official documentation. It explains all in details.
QNetworkRequest
QNetworkAccessManager

How to get image directly?

Follwing webpage includes light adult contents. Please do not click link if you don't want it.
go to : http://www.hqasians.com/tgp/bigasiantits/MaiNishida/at.htm
you can see several thumb images.
click one of them. you can see large image.
Check current page url. It will be like ~~~~~~~~~~~~~~~~/tgp/bigasiantits/MaiNishida/images/01.jpg
you can know how to access another image by changing last .jpg name of whole url
change 01.jpg to 02.jpg and enter.
But, you will encounter website's main page not 02.jpg.
Is this security way to block direct access by that site ?
Is there any work-around way to get image directly?
Following is my codes.
InputStream bmis;
bmis = new URL(params[0]).openStream();
final Drawable image =
new BitmapDrawable(BitmapFactory.decodeStream(new FlushedInputStream(bmis)));
if(image != null)
{
activity.setContentView(imageSwitcher);
imageSwitcher.setImageDrawable(image);
}
I'm only guessing here, but I think what this site does is to check the "Referer" field from the HTTP request header to check whether the request came from within the site, or from outside.
It isn't a secure way of blocking direct access. In fact, there's an workaround, but I don't think the site rules allow me to write it here, so, you'll have to figure out yourself.
It's because of the Referrer. You have to be referred by that main page to open the picture.
Sorry I'm not sure how to use Android, but C# code should look like this:
static void Main(string[] args)
{
for (int i = 1; i <= 15; i++)
{
HttpWebRequest request =
WebRequest.Create(
string.Format("http://www.hqasians.com/tgp/bigasiantits/MaiNishida/images/{0:00}.jpg", i)
) as HttpWebRequest;
request.Credentials = CredentialCache.DefaultCredentials;
request.Referer = "http://www.hqasians.com/tgp/bigasiantits/MaiNishida/at.htm";
request.Method = "POST";
WebResponse response = request.GetResponse();
string inputFile = string.Format("{0}.jpg", i);
Console.WriteLine(response.ResponseUri.AbsoluteUri);
using (Stream file = File.OpenWrite(inputFile))
{
CopyStream(response.GetResponseStream(), file);
}
}
}
/// <summary>
/// Copies the contents of input to output. Doesn't close either stream.
/// </summary>
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8 * 1024];
int len;
while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, len);
}
}
The CopyStream method is got from here: How do I save a stream to a file in C#?

Resources