我目前正在尝试使用Alamofire和Swift 5将照片从我的iOS设备上传到运行Wt的Web服务器,但是这样做时出现了分割错误。这是我的Swift代码:
static func setProfilePhoto(apiKey: String, imageData: Data, promise: Promise) {
DispatchQueue.global(qos: .userInitiated).async {
AF.upload(multipartFormData: { multiData in
multiData.append(imageData, withName: "image", fileName: "file.png", mimeType: "image/png")
}, to: "[Image URL redacted]", headers: ["api-key": apiKey]).validate().response { response in
switch response.result {
case .success(_):
promise.success(nil)
case .failure(_):
promise.failure("\(response.response?.statusCode ?? -1): \(response.bodyString ?? "")")
}
}
}
}
这是我的C ++实现,带有段注释的行注释如下:
void ApiPost::setPhoto() {
if (request_.contentType().rfind("multipart/form-data", 0) != 0) {
response_.out() << "Invalid Content-Type! Required: [multipart/form-data] Given: [" + request_.contentType() + "]";
response_.setStatus(400);
return;
}
const std::string token = request_.headerValue("api-key");
std::string photoType = *request_.getParameter("type");
SessionManager session(pool_);
Wt::Dbo::Transaction transaction(session);
try {
std::string id = DatabaseUtils::verifyAuthToken(session, token);
if (id.empty()) {
response_.out() << "Invalid authorization token";
response_.setStatus(401);
return;
}
Wt::Dbo::ptr<UserSettings> settings = session.find<UserSettings>().where("user_id = ?").bind(id);
// Delete previous file if it exists
if (photoType == "profile" && settings->profilePicPath_.length() > 0)
std::filesystem::remove(settings->profilePicPath_);
else if (photoType == "background" && settings->bkgrndPicPath_.length() > 0)
std::filesystem::remove(settings->bkgrndPicPath_);
Wt::Http::UploadedFile photo = request_.uploadedFiles().begin()->second;
photo.stealSpoolFile(); // Segfault here
std::string destPath = Statics::getBasePath() + "/photos/" + id + "/";
std::filesystem::create_directories(destPath);
std::fstream file(photo.spoolFileName(), std::ios::in | std::ios::binary);
destPath += HashUtils::sha256Random() + drodilMime::Detector::detectToExtension(file);
file.close();
std::filesystem::rename(photo.spoolFileName(), destPath);
if (photoType == "profile")
settings.modify()->profilePicPath_ = destPath;
else
settings.modify()->bkgrndPicPath_ = destPath;
std::filesystem::remove(photo.spoolFileName());
}
catch (Wt::Dbo::Exception& e) {
std::cout << e.what() << std::endl;
response_.out() << e.what();
response_.setStatus(500);
return;
}
catch (std::exception& e) {
std::cout << e.what() << std::endl;
response_.out() << e.what();
response_.setStatus(500);
return;
}
}
这是我得到的GDB错误:
0x0000000000810b82 in Wt::Http::UploadedFile::stealSpoolFile (this=0x7ffff2ebe1a0) at /home/jack/Build/vcpkg/buildtrees/wt/src/699342a1a5-7e5d5ddf44.clean/src/Wt/Http/Request.C:84
我尝试不使用stealSpoolFile()
,但它仍然存在段错误。我检查了Wt用file
命令创建的实际临时文件,它返回了data
而不是PNG image data...
的类型。奇怪的是,此代码在使用Postman时有效,但我担心它会出现段错误,而不是在没有错误时抛出异常。我有什么办法既可以解决可能导致问题的Swift代码,又可以防止由于数据格式错误而导致以后的段错误发生?