Segfault从Alamofire将PNG图片上传到Wt服务器

时间:2020-09-05 16:51:44

标签: c++ swift alamofire wt

我目前正在尝试使用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代码,又可以防止由于数据格式错误而导致以后的段错误发生?

0 个答案:

没有答案