CppCMS支持文件上传

长平狐 发布于 2012/08/28 16:36
阅读 568
收藏 0

HTTP文件上传

先制作一个简单的html页面,只包含了一个form

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
          "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    test upload
  </head>

  <body>
    <form method="post" name="submit" enctype="multipart/form-data">
      <input type="file" name="fileField"><br /><br />
      <input type="submit" name="submit" value="Submit">
    </form>
  </body>

</html>

form采用post方法提交. enctype的内容应该填写MIME_type,规定from的数据发送给服务器之前如何编码。

这里为了文件上传,必须指定multipart/form-data,也就是要求不要编码。

默认的enctype值是application/x-www-form-urlencoded,会对字符进行编码。

具体参考文档:http://www.w3school.com.cn/tags/att_form_enctype.asp


MIME

因为已经涉及到MIME,这里顺便介绍一下。全称是Multipurpose Internet Mail Extensions. 

这个对mail的扩展协议允许mail message能够支持非ASCII字符,二进制格式附件等多种格式。

它的写法格式是:

Content-Type: [type]/[subtype]; parameter
比如multipart是 type, form-data是 subtype。

具体请参考:http://zh.wikipedia.org/wiki/MIME

HTTP协议有时候也会使用MIME,但并不完全遵循MIME。


CppCMS示例

这个程序很简单,upload 一个pdf文件,然后保存到文件系统。我没有使用CppCMS的Form类,因为那是用C++类渲染HTML Form以及里面的html tags。就像JSF一样,会把事情搞复杂。我并不欣赏这种设计。因此我用的是CppCMS的最基本的方法,从request里获取上传的文件对象,然后保存到磁盘上。因此我的例子比CppCMS的example更好理解。

首先创建CMake工程,目录结构如下:

chenshu@chenshu-beijing:~/work/research/upload$ tree
.
├── CMakeLists.txt
├── config.js
├── include
│   ├── controller
│   │   └── upload_site.h
│   └── model
│       └── content.h
├── src
│   ├── CMakeLists.txt
│   ├── controller
│   │   └── upload_site.cpp
│   ├── main.cpp
│   └── view
│       └── upload.cpp
└── template
    └── upload.tmpl

7 directories, 9 files

因为CppCMS也是一个MVC架构,controller目录中的upload_site.cpp负责:

1.负责调用渲染引擎,生成并返回网页

2.将不同的HTTP URL映射到不同的函数


template目录存放了要渲染的网页模板文件。

view目录存放了CppCMS解析模板文件生成的C++类

model存放了渲染网页时需要的数据


现在看一下config.js,配置很简单:

{
    "service" : {
	"ip":"0.0.0.0",
        "api" : "http",
        "port" : 8081
    },
    "http" : {
        "script_names" : ["/cppcms"]
    }
}

好,将一开始的html页面转成upload.tmpl文件。

<% c++ #include "model/content.h" %>
<% skin upload %>
<% view upload_view uses content::upload_content %>
<% template render() %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    test upload
  </head>

  <body>
    <form method="post" action="./process_uploaded_file" name="submit" enctype="multipart/form-data">
      <input type="file" name="fileField"><br /><br />
      <input type="submit" name="submit" value="Submit">
    </form>
  </body>

</html>
<% end template %>
<% end view %>
<% end skin %>

model/content.h就是一个目前什么都没有的C++类,以便日后使用:

#ifndef CONTENT_H
#define CONTENT_H

#include <cppcms/view.h>

namespace content  {

    struct upload_content : public cppcms::base_content {

    };
}

#endif

现在重点看一下controller,

upload_site.h

#include <cppcms/application.h>
#include <cppcms/applications_pool.h>
#include <cppcms/service.h>

class upload_site : public cppcms::application {
public:
    upload_site(cppcms::service &srv);
    void upload_page();
    void process_uploaded_file();
};

upload_site.cpp

#include "controller/upload_site.h"
#include <cppcms/url_dispatcher.h>
#include "model/content.h"
#include <cppcms/http_file.h>

using namespace std;


upload_site::upload_site(cppcms::service &srv):cppcms::application(srv) {
    //web page
    dispatcher().assign("/upload" , &upload_site::upload_page, this);

    dispatcher().assign("/process_uploaded_file" , &upload_site::process_uploaded_file, this);
}

void upload_site::upload_page() { 
  content::upload_content content;
  render("upload","upload_view", content);
}

void upload_site::process_uploaded_file() {
  if(request().request_method()=="POST") {
    cppcms::http::request::files_type files = request().files();
    int size = files.size();
    booster::shared_ptr<cppcms::http::file> file = files.at(0);
    string file_name = file->filename();
    file->save_to("/home/chenshu/"+file_name);
  }
}

我的src/CMakeLIsts.txt

cmake_minimum_required(VERSION 2.8)
set(CMAKE_BUILD_TYPE Debug)
set(TEMPLATE_DIR ${CMAKE_SOURCE_DIR}/template)
set(VIEW_DIR ${CMAKE_SOURCE_DIR}/src/view)

find_package (Threads)
find_package(Boost COMPONENTS system filesystem REQUIRED)

include_directories(${CMAKE_SOURCE_DIR}/include)
add_definitions(-Wall)

add_custom_command(
  OUTPUT ${VIEW_DIR}/upload.cpp
  COMMAND cppcms_tmpl_cc ${TEMPLATE_DIR}/upload.tmpl -o ${VIEW_DIR}/upload.cpp
  DEPENDS ${TEMPLATE_DIR}/upload.tmpl
)

AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src CPP_LIST1)
set(CPP_LIST2 ${VIEW_DIR}/upload.cpp )
AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src/controller CPP_LIST3)
add_executable(upload ${CPP_LIST1} ${CPP_LIST2} ${CPP_LIST3})

target_link_libraries(upload ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} cppcms booster)

编译运行后,通过浏览器访问 http://localhost:8081/cppcms/upload

然后upload一个pdf文件。到/home/chenshu/下寻找这个pdf文件。

我用md5sum对比了源文件和网站保存的文件,md5相同。


成功。









原文链接:http://blog.csdn.net/sheismylife/article/details/7648106
加载中
返回顶部
顶部