mirror of https://gitee.com/bigwinds/arangodb
foxx file upload
This commit is contained in:
parent
f5aa621536
commit
81db41763f
|
@ -32,6 +32,7 @@
|
|||
#include "Basics/FileUtils.h"
|
||||
#include "Basics/files.h"
|
||||
#include "Basics/logging.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "HttpServer/HttpServer.h"
|
||||
#include "Rest/HttpRequest.h"
|
||||
|
||||
|
@ -77,7 +78,7 @@ Handler::status_t RestUploadHandler::execute () {
|
|||
return status_t(Handler::HANDLER_DONE);
|
||||
}
|
||||
|
||||
char* filename = NULL;
|
||||
char* filename = nullptr;
|
||||
|
||||
if (TRI_GetTempName("uploads", &filename, false) != TRI_ERROR_NO_ERROR) {
|
||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL, "could not generate temp file");
|
||||
|
@ -91,8 +92,28 @@ Handler::status_t RestUploadHandler::execute () {
|
|||
filename,
|
||||
relative);
|
||||
|
||||
char const* body = _request->body();
|
||||
size_t bodySize = _request->bodySize();
|
||||
|
||||
bool found;
|
||||
char const* value = _request->value("multipart", found);
|
||||
bool multiPart = false;
|
||||
|
||||
if (found) {
|
||||
multiPart = triagens::basics::StringUtils::boolean(value);
|
||||
|
||||
if (multiPart) {
|
||||
if (! parseMultiPart(body, bodySize)) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, relative);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, filename);
|
||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL, "invalid multipart request");
|
||||
return status_t(Handler::HANDLER_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
FileUtils::spit(string(filename), _request->body(), _request->bodySize());
|
||||
FileUtils::spit(string(filename), body, bodySize);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, filename);
|
||||
}
|
||||
catch (...) {
|
||||
|
@ -111,16 +132,157 @@ Handler::status_t RestUploadHandler::execute () {
|
|||
|
||||
TRI_json_t json;
|
||||
|
||||
TRI_InitObjectJson(TRI_CORE_MEM_ZONE, &json);
|
||||
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, &json, "filename", TRI_CreateStringJson(TRI_CORE_MEM_ZONE, fullName, strlen(fullName)));
|
||||
TRI_InitObjectJson(TRI_UNKNOWN_MEM_ZONE, &json);
|
||||
TRI_Insert3ObjectJson(TRI_UNKNOWN_MEM_ZONE, &json, "filename", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, fullName, strlen(fullName)));
|
||||
|
||||
generateResult(HttpResponse::CREATED, &json);
|
||||
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &json);
|
||||
TRI_DestroyJson(TRI_UNKNOWN_MEM_ZONE, &json);
|
||||
|
||||
// success
|
||||
return status_t(Handler::HANDLER_DONE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parses a multi-part request body and determines the boundaries of
|
||||
/// its first element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestUploadHandler::parseMultiPart (char const*& body,
|
||||
size_t& length) {
|
||||
char const* beg = _request->body();
|
||||
char const* end = beg + _request->bodySize();
|
||||
|
||||
while (beg < end && (*beg == '\r' || *beg == '\n' || *beg == ' ')) {
|
||||
++beg;
|
||||
}
|
||||
|
||||
// find delimiter
|
||||
char const* ptr = beg;
|
||||
while (ptr < end && *ptr == '-') {
|
||||
++ptr;
|
||||
}
|
||||
|
||||
while (ptr < end && *ptr != '\r' && *ptr != '\n') {
|
||||
++ptr;
|
||||
}
|
||||
if (ptr == beg) {
|
||||
// oops
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string const delimiter(beg, ptr - beg);
|
||||
if (ptr < end && *ptr == '\r') {
|
||||
++ptr;
|
||||
}
|
||||
if (ptr < end && *ptr == '\n') {
|
||||
++ptr;
|
||||
}
|
||||
|
||||
std::vector<std::pair<char const*, size_t>> parts;
|
||||
|
||||
while (ptr < end) {
|
||||
char const* p = TRI_IsContainedMemory(ptr, end - ptr, delimiter.c_str(), delimiter.size());
|
||||
if (p == nullptr || p + delimiter.size() + 2 >= end || p - 2 <= ptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char const* q = p;
|
||||
if (*(q - 1) == '\n') {
|
||||
--q;
|
||||
}
|
||||
if (*(q - 1) == '\r') {
|
||||
--q;
|
||||
}
|
||||
|
||||
parts.push_back(std::make_pair(ptr, q - ptr));
|
||||
ptr = p + delimiter.size();
|
||||
if (*ptr == '-' && *(ptr + 1) == '-') {
|
||||
// eom
|
||||
break;
|
||||
}
|
||||
if (*ptr == '\r') {
|
||||
++ptr;
|
||||
}
|
||||
if (ptr < end && *ptr == '\n') {
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& part : parts) {
|
||||
auto ptr = part.first;
|
||||
auto end = part.first + part.second;
|
||||
char const* data = nullptr;
|
||||
|
||||
while (ptr < end) {
|
||||
while (ptr < end && *ptr == ' ') {
|
||||
++ptr;
|
||||
}
|
||||
if (ptr < end && (*ptr == '\r' || *ptr == '\n')) {
|
||||
// end of headers
|
||||
if (*ptr == '\r') {
|
||||
++ptr;
|
||||
}
|
||||
if (ptr < end && *ptr == '\n') {
|
||||
++ptr;
|
||||
}
|
||||
data = ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
// header line
|
||||
char const* eol = TRI_IsContainedMemory(ptr, end - ptr, "\r\n", 2);
|
||||
|
||||
if (eol == nullptr) {
|
||||
eol = TRI_IsContainedMemory(ptr, end - ptr, "\n", 1);
|
||||
}
|
||||
|
||||
if (eol == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char const* colon = TRI_IsContainedMemory(ptr, end - ptr, ":", 1);
|
||||
if (colon == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char const* p = colon;
|
||||
while (p > ptr && *(p - 1) == ' ') {
|
||||
--p;
|
||||
}
|
||||
|
||||
++colon;
|
||||
while (colon < eol && *colon == ' ') {
|
||||
++colon;
|
||||
}
|
||||
|
||||
char const* q = eol;
|
||||
while (q > ptr && *(q - 1) == ' ') {
|
||||
--q;
|
||||
}
|
||||
|
||||
ptr = eol;
|
||||
if (*ptr == '\r') {
|
||||
++ptr;
|
||||
}
|
||||
if (ptr < end && *ptr == '\n') {
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
body = data;
|
||||
length = static_cast<size_t>(end - data);
|
||||
|
||||
// stop after the first found element
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -74,6 +74,14 @@ namespace triagens {
|
|||
|
||||
Handler::status_t execute ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parses a multi-part request body and determines the boundaries of
|
||||
/// its first element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool parseMultiPart (char const*&,
|
||||
size_t&);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,10 +124,11 @@
|
|||
$.ajax({
|
||||
type: "POST",
|
||||
async: false,
|
||||
url: '/_api/upload',
|
||||
url: '/_api/upload?multipart=true',
|
||||
contentType: "multipart/form-data",
|
||||
data: self.file,
|
||||
processData: false,
|
||||
contentType: 'application/octet-stream',
|
||||
cache: false,
|
||||
complete: function(res) {
|
||||
if (res.readyState === 4) {
|
||||
if (res.status === 201) {
|
||||
|
@ -737,7 +738,7 @@
|
|||
width: "336px"
|
||||
});
|
||||
$("#upload-foxx-zip").uploadFile({
|
||||
url: "/_api/upload",
|
||||
url: "/_api/upload?multipart=true",
|
||||
allowedTypes: "zip",
|
||||
onSuccess: this.installFoxxFromZip.bind(this)
|
||||
});
|
||||
|
|
|
@ -129,13 +129,11 @@ static int ExtractCurrentFile (unzFile uf,
|
|||
|
||||
// cannot write to outfile. this may be due to the target directory missing
|
||||
if (fout == NULL && ! skipPaths && filenameWithoutPath != (char*) filenameInZip) {
|
||||
char* d;
|
||||
|
||||
char c = *(filenameWithoutPath - 1);
|
||||
*(filenameWithoutPath - 1) = '\0';
|
||||
|
||||
// create target directory recursively
|
||||
d = TRI_Concatenate2File(outPath, filenameInZip);
|
||||
char* d = TRI_Concatenate2File(outPath, filenameInZip);
|
||||
TRI_CreateRecursiveDirectory(d);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, d);
|
||||
|
||||
|
@ -144,6 +142,17 @@ static int ExtractCurrentFile (unzFile uf,
|
|||
// try again
|
||||
fout = fopen(fullPath, "wb");
|
||||
}
|
||||
else if (fout == nullptr) {
|
||||
// try to create the target directory recursively
|
||||
char* d = TRI_Concatenate2File(outPath, filenameInZip);
|
||||
// strip filename so we only have the directory name
|
||||
char* dir = TRI_Dirname(d);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, d);
|
||||
TRI_CreateRecursiveDirectory(dir);
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, dir);
|
||||
// try again
|
||||
fout = fopen(fullPath, "wb");
|
||||
}
|
||||
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, fullPath);
|
||||
|
||||
|
|
Loading…
Reference in New Issue