Na tej stronie zaprezentowano korzystanie z API z poziomu języka C++ na przykładzie przetwarzania pliku zip.
W celu przesłania pliku do przetworzenia na serwer należy wykonać zapytanie POST
na adres /nlprest2/base/upload
. W ciele zapytania należy umieścić plik w formacie binary/octet-stream
. Odpowiedzią na tak skonstruowane zapytanie będzie ID pliku.
Następnie korzystając z otrzymanego ID pliku można skonstruować zapytanie w formacie lpmn, oraz rozpocząć jego przetwarzanie przy użyciu metody POST /nlprest2/base/startTask
zwróci ona ID zadania. Metoda wymaga dodatkowo podanie adresu email użytownika.
Status przetwarzania zapytania sprawdzamy metodą GET /nlprest2/base/getStatus/{IDzadania}
. Jeśli przetwarzanie się zakończyło możemy pobrać plik metodą GET /nlprest2/base/download/{IDpliku}
.
https://wiki.clarin-pl.eu/pl/nlpws/nlprest2/asynprocess
https://wiki.clarin-pl.eu/pl/nlpws/nlprest2/upload
W poniższym przykładzie do komunikacji za pomocą protokołu HTTP użyta została biblioteka CPP REST SDK, jednak możliwe jest użycie dowolnej biblioteki.
Kompletną realizację przykładu można znaleźć w repozytorium.
W celu przesłania pliku jako binary/octet-stream
należy najpierw zapisać wszystkie jego bajty do kontenera w tym wypadku std::vector<unsigned char>
.
std::vector<unsigned char> read_file_bytes(const char *filename)
{
// open the file:
std::ifstream file(filename, std::ios::binary);
if (file.is_open())
{
printf("Opened file %s \n", filename);
}
else
{
std::string error_msg = filename;
error_msg = "Failed to open file " + error_msg;
throw std::runtime_error(error_msg.c_str());
}
// Stop eating new lines in binary mode!!!
file.unsetf(std::ios::skipws);
// get its size:
std::streampos fileSize;
file.seekg(0, std::ios::end);
fileSize = file.tellg();
file.seekg(0, std::ios::beg);
// reserve capacity
std::vector<unsigned char> vec;
vec.reserve(fileSize);
// read the data:
vec.insert(vec.begin(),
std::istream_iterator<unsigned char>(file),
std::istream_iterator<unsigned char>());
printf("file read\n");
return vec;
}
Następnie zapisane w taki sposób bajty są zapisywane w ciele zapytania HTTP.
std::string upload_file(const char *filename, const char *url)
{
http_client client(U(url));
http_request request(methods::POST);
std::string result;
request.headers().add("Content-Type", "application/octet-stream");
request.set_body(file_helper::read_file_bytes(filename));
printf("body set as bytes\n");
pplx::task<void> requestTask = client.request(request)
.then([&result](http_response response) {
stringstreambuf ss;
result = response.extract_string().get();
});
requestTask.wait();
return result;
}
Analogicznie otrzymany później plik wynikowy możemy zapisać do pliku lokalnego.
void write_file_bytes(const char *filename, std::vector<unsigned char> &fileBytes)
{
std::ofstream file(filename, std::ios::out | std::ios::binary);
std::copy(fileBytes.cbegin(), fileBytes.cend(),
std::ostream_iterator<unsigned char>(file));
printf("File saved: %s\n", filename);
}
W celu wysłania zapytania lpmn należy dodatkowo umieścić swój email.
auto task = "any2txt|wcrft2|wsd"s;
auto user = "email@email.com"s; // Please use your email
auto fileid = APIexample::upload_file("file.zip","https://ws.clarin-pl.eu/nlprest2/base/upload");
auto lpmn = "filezip("+fileid+")|"+task+"|dir|makezip";
web::json::value data;
data["lpmn"] = web::json::value::string(lpmn);
data["user"] = web::json::value::string(user);
data = APIexample::process(data,url);
Następnie zgodnie z dokumentacją API przetwarzamy wysłany plik.
web::json::value process(web::json::value data, std::string url)
{
auto doc = data.serialize();
auto taskid = http_helper::post_get_string((url + "/startTask").c_str(), doc);
std::this_thread::sleep_for(std::chrono::milliseconds(200));
auto resp = http_helper::get_json((url + "/getStatus/" + taskid).c_str());
auto status = resp.at("status").as_string();
while (status == "QUEUE" or status == "PROCESSING")
{
printf("STATUS: %s \n", status.c_str());
std::this_thread::sleep_for(std::chrono::milliseconds(500));
resp = http_helper::get_json((url + "/getStatus/" + taskid).c_str());
status = resp.at("status").as_string();
}
if (status == "ERROR")
{
printf("Error %s \n", resp.at("value").as_string().c_str());
}
return resp.at("value");
}
Funkcja process
zwraca JSONArray z nazwami i ID pliku z wynikami. W tym przykładzie pobieramy pojedynczy plik.
data = APIexample::process(data,url);
if (!data.is_null())
{
data = data[0]["fileID"];
APIexample::download_file((url+"/download"+data.as_string()).c_str(),output_filename);
}