리스팅 까지 진행됫고, 업/다운을 Drogon을 통해 구현한다
---
## 1. 서버 기능 구현
### 1-1. Drogon Contoller 구현
Drogon Contoller 등록 진행을 한다
( 아래 작업을 해야 빌드시 인식이 됨 )
```
cd /root/drogon2/drogon/build/drogon_ctl
drogon_ctl create controller FileController
```
---
### 1-2. 업/다운 구현
소스 위치할 경로 ( /root/drogon2/drogon/build/drogon_ctl/testAPI/controllers )
FileController.h
#pragma once
#include
using namespace drogon;
class FileController : public HttpController
{
public:
std:: string _storagePath = "/root/storage/";
METHOD_LIST_BEGIN
// "/upload" 경로의 POST 요청 처리
ADD_METHOD_TO(FileController::handleUpload, "/upload", Post);
// "/download/{filename}" 경로의 GET 요청 처리
ADD_METHOD_TO(FileController::handleDownload, "/download/{1}", Get);
METHOD_LIST_END
// 메서드 선언
void handleUpload(const HttpRequestPtr& req, std::function&& callback);
void handleDownload(const HttpRequestPtr& req, std::function&& callback, const std::string& filename);
};
---
FileController.cc
#include "FileController.h"
#include
#include
// 업로드 핸들러
void FileController::handleUpload(const HttpRequestPtr& req, std::function&& callback)
{
Json::Value respStr;
HttpStatusCode code = k200OK;
MultiPartParser fileUpload;
do
{
if ( fileUpload.parse(req) != 0 )
{
code = k400BadRequest;
respStr = Json::Value("Multipart Format Invalid");
break ;
}
auto &file = fileUpload.getFiles()[0];
LOG_INFO << "file:" << file.getFileName()
<< " (extension=" << file.getFileExtension()
<< ", type=" << file.getFileType()
<< ", len=" << file.fileLength()
<< ", md5=" << file.getMd5() << ")";
std::string uploadPath =_storagePath + file.getFileName();
LOG_INFO << "uploadPath:" << uploadPath.c_str();
if ( file.saveAs(uploadPath) != 0 )
{
code = k500InternalServerError;
respStr = Json::Value("Internal Server Error");
break ;
}
}
while(false);
auto resp = HttpResponse::newHttpResponse();
resp->setStatusCode(code);
callback(resp);
}
// 다운로드 핸들러
void FileController::handleDownload(const HttpRequestPtr& req, std::function&& callback, const std::string& filename)
{
std::string filePath = _storagePath.c_str() + filename;
if ( std::ifstream(filePath).good() == true )
{
auto resp = HttpResponse::newFileResponse(filePath.c_str(), filename.c_str());
resp->setContentTypeCode(CT_APPLICATION_OCTET_STREAM);
resp->addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
callback(resp);
}
else
{
auto resp = HttpResponse::newHttpResponse();
resp->setStatusCode(k404NotFound);
callback(resp);
}
}
작업 이후 아래 경로로 이동후 make
```
cd /root/drogon2/drogon/build/drogon_ctl/testAPI/build
make
```
---
### 1-3. drogon 설정 수정
/root/drogon2/drogon/build/drogon_ctl/testAPI/config.json 파일의
`client_max_body_size` 값을 수정한다 ( 기본 1M으로 되어있음 )
```
"client_max_body_size": "256M" # 기본 1M, 원하는 만큼 변경하면된다
```
위 값 수정하지않으면
413 Request Entity Too Large 에러를 리턴한다
이건 로그도 안찍어서 소스 뒤져봐야되는데, 머리아프다
위 작업 까지 완료되면 서버쪽은 완료된다
---
## 2. 클라이언트 기능 구현
아래 경로에 html 추가
/root/nginx/html/upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<h2>Upload a File</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" required>
<br><br>
<button type="submit">Send</button>
</form>
</body>