[6] Nginx Server Setup - Implementing Upload/Download + Simple Upload Client
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
With directory listing set up, let's implement file upload/download functionality using Drogon.
1. Server Function Implementation
1-1. Implementing Drogon Controller
Register the Drogon Controller. (This step is required for it to be recognized during the build.)
``` cd /root/drogon2/drogon/build/drogon_ctl drogon_ctl create controller FileController ```
1-2. Implement Upload/Download Functionality
Source path: `/root/drogon2/drogon/build/drogon_ctl/testAPI/controllers`
FileController.h
#pragma once #includeusing namespace drogon;
class FileController : public HttpController
{ public: std::string _storagePath = "/root/storage/"; METHOD_LIST_BEGIN // Handles POST requests for "/upload" ADD_METHOD_TO(FileController::handleUpload, "/upload", Post); // Handles GET requests for "/download/{filename}" ADD_METHOD_TO(FileController::handleDownload, "/download/{1}", Get); METHOD_LIST_END
// Method declarations 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 // Upload handler 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); }
// Download handler void FileController::handleDownload(const HttpRequestPtr& req, std::function
&& callback, const std::string& filename) { std::string filePath = _storagePath + filename; if (std::ifstream(filePath).good()) { 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); } }
After the above steps, navigate to the build directory and run `make`:
``` cd /root/drogon2/drogon/build/drogon_ctl/testAPI/build make ```
1-3. Modify Drogon Configuration
Edit `/root/drogon2/drogon/build/drogon_ctl/testAPI/config.json` and modify the `client_max_body_size` value (default is 1M).
``` "client_max_body_size": "256M" # Default is 1M, adjust as needed ```
If this value is not modified, a "413 Request Entity Too Large" error will be returned. With these modifications, the server setup is complete.
2. Client Function Implementation
Add an HTML file at the following path: `/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> </html>
3. NGINX Configuration
- Adjust the API alias settings - Also modify `client_max_body_size`
``` user nobody; worker_processes 10;
events { worker_connections 1024; use epoll; }
http { include mime.types; default_type application/octet-stream;
sendfile on; client_max_body_size 256m;
proxy_buffer_size 128k; proxy_buffers 4 256k;
server { listen 10099; server_name localhost;
location /doUpload { alias /root/nginx/html/; index upload.html; autoindex on; }
location /list { alias /root/storage/; autoindex on; # Enable directory listing autoindex_exact_size off; # Display file size in simplified format (optional) autoindex_localtime on; # Display file time in local time (optional) }
location /upload { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://127.0.0.1:8848; # Proxy target server }
location ~ ^/download/(.*) { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://127.0.0.1:8848/download/$1; # Pass captured variable to backend } } } ```
If a "413 Request Entity Too Large" error occurs, adjust `client_max_body_size`.
4. Verifying Operation
4-1. Verify Upload Operation
- Call the upload API and select a file using the client.
- The server should respond with 200 OK.
- Files are saved in the following path: ``` [root@vbox storage] $ ll Total 72 -rw-r--r--. 1 root root 66662 Nov 4 08:48 7.PNG -rw-r--r--. 1 nobody nobody 2 Nov 4 06:21 test.txt ```
You can also confirm this in the listing set up in “[5] NGINX Server Setup.”
4-2. Verify Download Operation
- In a web browser, go to `http://127.0.0.1:10099/download/7.PNG` to confirm file download functionality. (While it is possible to download from the listing page, use the API directly to test the download function.)
``` # Download with wget; file size should match expected size [root@vbox ~] $ wget http://127.0.0.1:10099/download/7.PNG --2024-11-04 08:59:27-- http://127.0.0.1:10099/download/7.PNG Connecting to 127.0.0.1:10099... connected. HTTP request sent, awaiting response... 200 OK Length: 66662 (65K) [application/octet-stream] Saving to: `7.PNG'
7.PNG 100%[=====================================================================>] 65.10K --.-KB/s in 0s
2024-11-04 08:59:27 (397 MB/s) - `7.PNG' saved [66662/66662] ```
Related Links
Recommended Link
- 공유 링크 만들기
- X
- 이메일
- 기타 앱
댓글
댓글 쓰기