Commit 91a24160 authored by Paweł Wegner's avatar Paweł Wegner

Upload: provide handle to uploaded file.

parent 388df4c5
......@@ -76,13 +76,13 @@ uint32_t UploadFileCallback::putData(char* data, uint32_t maxlength) {
uint64_t UploadFileCallback::size() { return file_.size(); }
void UploadFileCallback::done(EitherError<void> e) {
void UploadFileCallback::done(EitherError<IItem> e) {
auto lock = window_->stream_lock();
if (e.left()) {
std::cerr << "[FAIL] Upload: " << e.left()->code_ << " "
<< e.left()->description_ << "\n";
} else {
std::cerr << "[OK] Successfuly uploaded\n";
std::cerr << "[OK] Successfully uploaded " << e.right()->filename() << "\n";
}
emit window_->uploadProgressChanged(0, 0);
}
......
......@@ -86,7 +86,7 @@ class UploadFileCallback : public IUploadFileCallback {
void reset() override;
uint32_t putData(char* data, uint32_t maxlength) override;
uint64_t size() override;
void done(EitherError<void>) override;
void done(EitherError<IItem>) override;
void progress(uint32_t total, uint32_t now) override;
private:
......
......@@ -27,6 +27,7 @@
#include <tinyxml2.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include "Utility/Utility.h"
......@@ -411,6 +412,15 @@ IHttpRequest::Pointer AmazonS3::uploadFileRequest(const IItem& directory,
"PUT");
}
IItem::Pointer AmazonS3::uploadFileResponse(const IItem& item,
const std::string& filename,
uint64_t size,
std::istream&) const {
return util::make_unique<Item>(filename, getPath(item.id()) + "/" + filename,
size, std::chrono::system_clock::now(),
IItem::FileType::Unknown);
}
IHttpRequest::Pointer AmazonS3::downloadFileRequest(const IItem& item,
std::ostream&) const {
auto data = extract(item.id());
......
......@@ -77,6 +77,9 @@ class AmazonS3 : public CloudProvider {
IItem::Pointer createDirectoryResponse(const IItem& parent,
const std::string& name,
std::istream& response) const override;
IItem::Pointer uploadFileResponse(const IItem& parent,
const std::string& filename, uint64_t,
std::istream& response) const override;
void authorizeRequest(IHttpRequest&) const override;
bool reauthorize(int, const IHttpRequest::HeaderParameters&) const override;
......
......@@ -138,6 +138,13 @@ IHttpRequest::Pointer Box::uploadFileRequest(
return request;
}
IItem::Pointer Box::uploadFileResponse(const IItem&, const std::string&,
uint64_t, std::istream& response) const {
Json::Value json;
response >> json;
return toItem(json["entries"][0]);
}
IHttpRequest::Pointer Box::downloadFileRequest(const IItem& item,
std::ostream&) const {
return http()->create(endpoint() + "/2.0/files/" + item.id() + "/content",
......
......@@ -70,6 +70,9 @@ class Box : public CloudProvider {
const IItem&, std::istream&, std::string& next_page_token) const override;
std::string getItemUrlResponse(const IItem& item,
std::istream& response) const override;
IItem::Pointer uploadFileResponse(const IItem& parent,
const std::string& filename, uint64_t,
std::istream& response) const override;
IItem::Pointer toItem(const Json::Value&) const;
......
......@@ -124,7 +124,9 @@ class UploadFileCallback : public cloudstorage::IUploadFileCallback {
uint64_t size() override { return size_; }
void done(cloudstorage::EitherError<void> e) override { callback_(e); }
void done(cloudstorage::EitherError<cloudstorage::IItem> e) override {
callback_(e);
}
void progress(uint32_t, uint32_t) override {}
......@@ -522,6 +524,12 @@ IItem::Pointer CloudProvider::moveItemResponse(const IItem&, const IItem&,
return getItemDataResponse(response);
}
IItem::Pointer CloudProvider::uploadFileResponse(const IItem&,
const std::string&, uint64_t,
std::istream& response) const {
return getItemDataResponse(response);
}
std::string CloudProvider::getItemUrlResponse(const IItem&,
std::istream&) const {
return "";
......
......@@ -24,6 +24,7 @@
#ifndef CLOUDPROVIDER_H
#define CLOUDPROVIDER_H
#include <cstdint>
#include <mutex>
#include <sstream>
#include <thread>
......@@ -235,6 +236,11 @@ class CloudProvider : public ICloudProvider,
virtual IItem::Pointer moveItemResponse(const IItem&, const IItem&,
std::istream&) const;
virtual IItem::Pointer uploadFileResponse(const IItem& parent,
const std::string& filename,
uint64_t size,
std::istream& response) const;
/**
* Used by default implementation of createDirectoryAsync, should translate
* response into new directory's item object.
......
......@@ -207,6 +207,16 @@ std::vector<IItem::Pointer> Dropbox::listDirectoryResponse(
return result;
}
IItem::Pointer Dropbox::uploadFileResponse(const IItem&,
const std::string& name, uint64_t,
std::istream& stream) const {
Json::Value response;
stream >> response;
return util::make_unique<Item>(
name, response["path"].asString(), response["bytes"].size(),
std::chrono::system_clock::now(), IItem::FileType::Unknown);
}
IItem::Pointer Dropbox::createDirectoryResponse(const IItem&,
const std::string&,
std::istream& response) const {
......
......@@ -74,6 +74,9 @@ class Dropbox : public CloudProvider {
IItem::Pointer createDirectoryResponse(const IItem& parent,
const std::string& name,
std::istream& response) const override;
IItem::Pointer uploadFileResponse(const IItem& parent,
const std::string& filename, uint64_t,
std::istream& response) const override;
void authorizeRequest(IHttpRequest&) const override;
......
......@@ -78,10 +78,14 @@ IHttpRequest::Pointer GoogleDrive::uploadFileRequest(
std::ostream& suffix_stream) const {
const std::string separator = "fWoDm9QNn3v3Bq3bScUX";
const Item& item = static_cast<const Item&>(f);
IHttpRequest::Pointer request = http()->create(
endpoint() + "/upload/drive/v3/files?uploadType=multipart", "POST");
IHttpRequest::Pointer request =
http()->create(endpoint() + "/upload/drive/v3/files", "POST");
request->setHeaderParameter("Content-Type",
"multipart/related; boundary=" + separator);
request->setParameter("uploadType", "multipart");
request->setParameter("fields",
"id,name,thumbnailLink,trashed,"
"mimeType,iconLink,parents");
Json::Value request_data;
request_data["name"] = filename;
request_data["parents"].append(item.id());
......
......@@ -192,13 +192,14 @@ class TransferListener : public mega::MegaTransferListener, public Listener {
upload_callback_->progress(t->getTotalBytes(), t->getTransferredBytes());
}
void onTransferFinish(MegaApi*, MegaTransfer*, MegaError* e) override {
void onTransferFinish(MegaApi*, MegaTransfer* t, MegaError* e) override {
auto r = shared_from_this();
provider_->removeRequestListener(r);
std::unique_lock<std::mutex> lock(mutex_);
if (e->getErrorCode() == 0)
if (e->getErrorCode() == 0) {
status_ = SUCCESS;
else {
node_ = t->getNodeHandle();
} else {
error_ = {e->getErrorCode(), e->getErrorString()};
status_ = FAILURE;
}
......@@ -217,6 +218,7 @@ class TransferListener : public mega::MegaTransferListener, public Listener {
IUploadFileCallback* upload_callback_ = nullptr;
MegaApi* mega_ = nullptr;
int transfer_ = 0;
MegaHandle node_ = 0;
};
struct Buffer {
......@@ -591,11 +593,11 @@ ICloudProvider::DownloadFileRequest::Pointer MegaNz::downloadFileAsync(
ICloudProvider::UploadFileRequest::Pointer MegaNz::uploadFileAsync(
IItem::Pointer item, const std::string& filename,
IUploadFileCallback::Pointer cb) {
auto r = std::make_shared<Request<EitherError<void>>>(shared_from_this());
auto r = std::make_shared<Request<EitherError<IItem>>>(shared_from_this());
auto callback = cb.get();
r->set(
[=](Request<EitherError<void>>::Pointer r) {
ensureAuthorized<EitherError<void>>(r, [=] {
[=](Request<EitherError<IItem>>::Pointer r) {
ensureAuthorized<EitherError<IItem>>(r, [=] {
std::string cache = temporaryFileName();
{
std::fstream mega_cache(cache.c_str(),
......@@ -614,9 +616,12 @@ ICloudProvider::UploadFileRequest::Pointer MegaNz::uploadFileAsync(
}
}
auto listener = Listener::make<TransferListener>(
[=](EitherError<void> e, Listener*) {
[=](EitherError<void> e, Listener* listener) {
std::remove(cache.c_str());
return r->done(e);
if (e.left()) return r->done(e.left());
std::unique_ptr<MegaNode> node(mega_->getNodeByHandle(
static_cast<TransferListener*>(listener)->node_));
r->done(toItem(node.get()));
},
this);
listener->upload_callback_ = callback;
......@@ -628,7 +633,7 @@ ICloudProvider::UploadFileRequest::Pointer MegaNz::uploadFileAsync(
});
},
[=](EitherError<void> e) { cb->done(e); });
[=](EitherError<IItem> e) { cb->done(e); });
return r->run();
}
......
......@@ -26,6 +26,7 @@
#include <json/json.h>
#include <sstream>
#include <iostream>
#include "Request/Request.h"
#include "Utility/Item.h"
#include "Utility/Utility.h"
......@@ -36,12 +37,14 @@ using namespace std::placeholders;
namespace cloudstorage {
namespace {
void upload(Request<EitherError<void>>::Pointer r, int sent,
void upload(Request<EitherError<IItem>>::Pointer r, int sent,
IUploadFileCallback* callback, Json::Value response) {
auto output = std::make_shared<std::stringstream>();
int size = callback->size();
auto length = std::make_shared<int>(0);
if (sent >= size) return r->done(nullptr);
if (sent >= size)
return r->done(
static_cast<OneDrive*>(r->provider().get())->toItem(response));
r->sendRequest(
[=](util::Output stream) {
std::vector<char> buffer(CHUNK_SIZE);
......@@ -56,10 +59,14 @@ void upload(Request<EitherError<void>>::Pointer r, int sent,
return request;
},
[=](EitherError<util::Output> e) {
if (e.left())
r->done(e.left());
else
upload(r, sent + *length, callback, response);
if (e.left()) return r->done(e.left());
try {
Json::Value json;
*output >> json;
upload(r, sent + *length, callback, json);
} catch (std::exception) {
r->done(Error{IHttpRequest::Failure, output->str()});
}
},
output, nullptr,
[=](uint32_t, uint32_t now) { callback->progress(size, sent + now); });
......@@ -75,10 +82,10 @@ std::string OneDrive::endpoint() const { return "https://api.onedrive.com"; }
ICloudProvider::UploadFileRequest::Pointer OneDrive::uploadFileAsync(
IItem::Pointer parent, const std::string& filename,
IUploadFileCallback::Pointer cb) {
auto r = std::make_shared<Request<EitherError<void>>>(shared_from_this());
auto r = std::make_shared<Request<EitherError<IItem>>>(shared_from_this());
auto callback = cb.get();
r->set(
[=](Request<EitherError<void>>::Pointer r) {
[=](Request<EitherError<IItem>>::Pointer r) {
auto output = std::make_shared<std::stringstream>();
r->sendRequest(
[=](util::Output) {
......@@ -99,7 +106,7 @@ ICloudProvider::UploadFileRequest::Pointer OneDrive::uploadFileAsync(
},
output);
},
[=](EitherError<void> e) { cb->done(e); });
[=](EitherError<IItem> e) { cb->done(e); });
return r->run();
}
......
......@@ -38,6 +38,8 @@ class OneDrive : public CloudProvider {
std::string name() const override;
std::string endpoint() const override;
IItem::Pointer toItem(const Json::Value&) const;
protected:
UploadFileRequest::Pointer uploadFileAsync(
IItem::Pointer, const std::string& filename,
......@@ -80,8 +82,6 @@ class OneDrive : public CloudProvider {
std::istream&) const override;
Token::Pointer refreshTokenResponse(std::istream&) const override;
};
IItem::Pointer toItem(const Json::Value&) const;
};
} // namespace cloudstorage
......
......@@ -81,6 +81,14 @@ IItem::Pointer PCloud::getItemDataResponse(std::istream& response) const {
return toItem(json["metadata"]);
}
IItem::Pointer PCloud::uploadFileResponse(const IItem&, const std::string&,
uint64_t,
std::istream& response) const {
Json::Value json;
response >> json;
return toItem(json["metadata"][0]);
}
IHttpRequest::Pointer PCloud::listDirectoryRequest(const IItem& item,
const std::string&,
std::ostream&) const {
......@@ -105,6 +113,7 @@ IHttpRequest::Pointer PCloud::uploadFileRequest(const IItem& directory,
req->setHeaderParameter("Content-Type", "application/octet-stream");
req->setParameter("folderid", directory.id());
req->setParameter("filename", util::Url::escape(filename));
req->setParameter("timeformat", "timestamp");
return req;
}
......
......@@ -67,6 +67,9 @@ class PCloud : public CloudProvider {
std::string getItemUrlResponse(const IItem& item,
std::istream& response) const override;
IItem::Pointer getItemDataResponse(std::istream& response) const override;
IItem::Pointer uploadFileResponse(const IItem& parent,
const std::string& filename, uint64_t,
std::istream& response) const override;
IItem::Pointer toItem(const Json::Value&) const;
......
......@@ -29,6 +29,7 @@
#include <json/json.h>
#include <cstring>
#include <iomanip>
#include <iostream>
namespace cloudstorage {
......@@ -150,6 +151,14 @@ IHttpRequest::Pointer WebDav::renameItemRequest(const IItem& item,
return request;
}
IItem::Pointer WebDav::uploadFileResponse(const IItem& item,
const std::string& filename,
uint64_t size, std::istream&) const {
return util::make_unique<Item>(filename, getPath(item.id()) + "/" + filename,
size, std::chrono::system_clock::now(),
IItem::FileType::Unknown);
}
IItem::Pointer WebDav::getItemDataResponse(std::istream& stream) const {
std::stringstream sstream;
sstream << stream.rdbuf();
......
......@@ -84,6 +84,9 @@ class WebDav : public CloudProvider {
IItem::Pointer createDirectoryResponse(const IItem& parent,
const std::string& name,
std::istream& response) const override;
IItem::Pointer uploadFileResponse(const IItem& parent,
const std::string& filename, uint64_t,
std::istream& response) const override;
IItem::Pointer toItem(const tinyxml2::XMLNode*) const;
......
......@@ -87,17 +87,17 @@ ICloudProvider::DownloadFileRequest::Pointer YandexDisk::downloadFileAsync(
ICloudProvider::UploadFileRequest::Pointer YandexDisk::uploadFileAsync(
IItem::Pointer directory, const std::string& filename,
IUploadFileCallback::Pointer callback) {
auto r = std::make_shared<Request<EitherError<void>>>(shared_from_this());
auto upload_url = [=](Request<EitherError<void>>::Pointer r,
auto r = std::make_shared<Request<EitherError<IItem>>>(shared_from_this());
auto path = directory->id();
if (path.back() != '/') path += "/";
path += filename;
auto upload_url = [=](Request<EitherError<IItem>>::Pointer r,
std::function<void(EitherError<std::string>)> f) {
auto output = std::make_shared<std::stringstream>();
r->sendRequest(
[=](util::Output) {
auto request =
http()->create(endpoint() + "/v1/disk/resources/upload", "GET");
std::string path = directory->id();
if (path.back() != '/') path += "/";
path += filename;
request->setParameter("path", path);
return request;
},
......@@ -113,8 +113,8 @@ ICloudProvider::UploadFileRequest::Pointer YandexDisk::uploadFileAsync(
},
output);
};
auto upload = [=](Request<EitherError<void>>::Pointer r, std::string url,
std::function<void(EitherError<void>)> f) {
auto upload = [=](Request<EitherError<IItem>>::Pointer r, std::string url,
std::function<void(EitherError<IItem>)> f) {
auto wrapper = std::make_shared<UploadStreamWrapper>(
std::bind(&IUploadFileCallback::putData, callback.get(), _1, _2),
callback->size());
......@@ -128,23 +128,23 @@ ICloudProvider::UploadFileRequest::Pointer YandexDisk::uploadFileAsync(
return request;
},
[=](EitherError<util::Output> e) {
(void)wrapper;
if (e.left())
f(e.left());
else
f(nullptr);
if (e.left()) return f(e.left());
IItem::Pointer item = util::make_unique<Item>(
filename, path, wrapper->size_, std::chrono::system_clock::now(),
IItem::FileType::Unknown);
f(item);
},
output, nullptr,
std::bind(&IUploadFileCallback::progress, callback.get(), _1, _2));
};
r->set(
[=](Request<EitherError<void>>::Pointer r) {
[=](Request<EitherError<IItem>>::Pointer r) {
upload_url(r, [=](EitherError<std::string> ret) {
if (ret.left()) r->done(ret.left());
upload(r, *ret.right(), [=](EitherError<void> e) { r->done(e); });
upload(r, *ret.right(), [=](EitherError<IItem> e) { r->done(e); });
});
},
[=](EitherError<void> e) { callback->done(e); });
[=](EitherError<IItem> e) { callback->done(e); });
return r->run();
}
......
......@@ -49,7 +49,7 @@ class ICloudProvider {
IRequest<EitherError<std::vector<IItem::Pointer>>>;
using GetItemRequest = IRequest<EitherError<IItem>>;
using DownloadFileRequest = IRequest<EitherError<void>>;
using UploadFileRequest = IRequest<EitherError<void>>;
using UploadFileRequest = IRequest<EitherError<IItem>>;
using GetItemDataRequest = IRequest<EitherError<IItem>>;
using DeleteItemRequest = IRequest<EitherError<void>>;
using CreateDirectoryRequest = IRequest<EitherError<IItem>>;
......@@ -420,7 +420,7 @@ class ICloudProvider {
virtual UploadFileRequest::Pointer uploadFileAsync(
IItem::Pointer parent, const std::string& path,
const std::string& filename,
UploadFileCallback callback = [](EitherError<void>) {}) = 0;
UploadFileCallback callback = [](EitherError<IItem>) {}) = 0;
};
} // namespace cloudstorage
......
......@@ -176,7 +176,7 @@ class IUploadFileCallback {
/**
* Called when the upload is finished sucessfully.
*/
virtual void done(EitherError<void>) = 0;
virtual void done(EitherError<IItem>) = 0;
/**
* Called when upload progress changed.
......@@ -235,7 +235,7 @@ using ListDirectoryPageCallback = std::function<void(EitherError<PageData>)>;
using ListDirectoryCallback =
std::function<void(EitherError<std::vector<IItem::Pointer>>)>;
using DownloadFileCallback = std::function<void(EitherError<void>)>;
using UploadFileCallback = std::function<void(EitherError<void>)>;
using UploadFileCallback = std::function<void(EitherError<IItem>)>;
using GetThumbnailCallback = std::function<void(EitherError<void>)>;
} // namespace cloudstorage
......
......@@ -39,7 +39,7 @@ UploadFileRequest::UploadFileRequest(std::shared_ptr<CloudProvider> p,
auto callback = cb.get();
set(
[=](Request::Pointer request) {
auto response_stream = std::make_shared<std::ostream>(&stream_wrapper_);
auto output = std::make_shared<std::stringstream>();
sendRequest(
[=](util::Output input) {
callback->reset();
......@@ -50,16 +50,18 @@ UploadFileRequest::UploadFileRequest(std::shared_ptr<CloudProvider> p,
stream_wrapper_.suffix_);
},
[=](EitherError<util::Output> e) {
if (e.left())
request->done(e.left());
else
request->done(nullptr);
if (e.left()) return request->done(e.left());
try {
request->done(provider()->uploadFileResponse(
*directory, filename, stream_wrapper_.size_, *output));
} catch (std::exception) {
request->done(Error{IHttpRequest::Failure, output->str()});
}
},
response_stream, nullptr,
std::bind(&UploadFileRequest::ICallback::progress, callback, _1,
_2));
output, nullptr, std::bind(&UploadFileRequest::ICallback::progress,
callback, _1, _2));
},
[=](EitherError<void> e) { cb->done(e); });
[=](EitherError<IItem> e) { cb->done(e); });
}
UploadFileRequest::~UploadFileRequest() { cancel(); }
......
......@@ -50,7 +50,7 @@ class UploadStreamWrapper : public std::streambuf {
pos_type position_;
};
class UploadFileRequest : public Request<EitherError<void>> {
class UploadFileRequest : public Request<EitherError<IItem>> {
public:
using ICallback = IUploadFileCallback;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment