# 8.1 上傳文件功能
前端是web前端,所以上傳文件的時候最終應該會是一個post請求。
這里的請求url類似如下:
http://192.168.2.107/upload/UploadAction
之后攜帶的數據便是文件的數據信息。
http上傳文件信息具有一定的格式,我們這用的web應用端是用的fastCGI進行解析,那么我們應該按照一定的數據個數進行解析。
##1 上傳協議格式解剖
下圖是我要上傳的文件,是一個文本文件。這樣能較為清晰地說明。
文本共有6行,是我隨便寫的內容。

下圖是web服務端接收到的協議的內容,

將其標記一下,如下圖所示。其中紅框里面就是第一副圖上文本的內容。綠框是協議格式的組成部分。
http協議規定,每一行之后要多增加一個'\n'和'\r',用來回車換行。每一行都有,下圖只綠框標識了三個而已。詳細的,可參考文章開頭推薦的兩篇博文知曉其原理。

但是我們會面臨一個問題,如果紅框的post數據就是我們要得到的文件,那么我們該如何把他截取出來。單純從字符串考慮是不能夠通過的,因為我們所傳輸的文件不可能只有文本文件,會有一些其他二進制文件,所以我們應該想辦法考慮一個可能通過內存數據截取的接口。
這一點如果用c語言或者c++語言貌似并不是什么難事。
##2、上傳插件選擇
簡單提一下思路,有3種方案,
(1)直接使用form表單
(2)使用別人開發的html控件。如FileUpload,zyUpload,等。上傳的插件非常多,百度一搜索一大把。
(3)其他語言開發的網頁插件。如ocx等。
選擇時的考量點在哪里?
純web網頁是用html+css+js開發的,網上找的開源html控件也是如此。自己直接使用form表單,那就需要自己編寫css和js代碼,這樣也能讓網頁整體風格樣式相同。
用別人的控件css和js都是現成的,開發人員需要把它嵌入進來,就跟調用接口一樣。但是風格和樣式就無法能夠確保是否和自己的網頁相同了。
如果是用別的語言開發網頁插件則另當別論,開發的難度以及將插件向自己網頁的集成是費時費力的環節。但是如果你熟悉此而不了解web網頁開發的話,用這種方法也未嘗不可。
所以說,沒有哪種方案是萬能的,關鍵是依據自己的項目進行取舍。
我最后選擇的是zyUpload,原因是使用簡單,樣式可控。
## 3、C++服務端解析
首先在nginx搭建一個location server。
```bash
location = /upload/UploadAction {
fastcgi_pass 127.0.0.1:8082;
fastcgi_index upload.cgi;
include fastcgi.conf;
}
```
通過fastcgi開啟一個后端服務程序upload.cgi處理。
該后臺程序大致處理流程如下:
1. 通過上面的文本固定形式,截取出文本文件內存數據。
2. 將得到的文件存入fastDFS中,并且該文件在fastDFS的唯一標識ID
3. 將文件存入fastDFS中的url路徑存入本地redis表中,以被展示使用
##redis存儲文件表結構
### 方案一:
redis表中存放兩張表
```cpp
/*-----------------------------------------------------------.
| 文件信息表(LIST) |
| Key: FILE_INFO_LIST |
| Value: file_id|url|filename|create time|user|type |
| redis 語句 |
| 插入 LPUSH key value |
| 查詢個數 LLEN key |
| 大于最大需要截斷 LTRIM key 0 max-1 |
| 查詢鏈表數據 LRANGE key 0 max-1 |
`-----------------------------------------------------------*/
```
本表中主要存放文件的基本信息
```cpp
/*------------------------------------------.
| 點擊量文件表 (ZSET) |
| Key: FILE_HOT_ZSET |
| Member: file_id |
| Score: pv |
| redis 語句 |
| ZINCRBY key increment member |
`------------------------------------------*/
```
本表中重要存放文件的下載量。
###方案二(推薦):
也可以將FILE_INFO_LIST拆分成多個表:
```cpp
/*------------------------------------------.
| 點擊量文件表 (ZSET) |
| Key: FILE_HOT_ZSET |
| Member: file_id |
| Score: pv |
| redis 語句 |
| ZINCRBY key increment member |
`------------------------------------------*/
#define FILE_HOT_ZSET "FILE_HOT_ZSET"
/*------------------------------------------.
| 文件ID和文件名對應表 (HASH) |
| Key: FILEID_NAME_HASH |
| field: file_id |
| value: file_name |
| redis 語句 |
| hset key field value |
| hget key field |
`------------------------------------------*/
#define FILEID_NAME_HASH "FILEID_NAME_HASH"
/*------------------------------------------.
| 文件ID和文件創建時間對應表 (HASH) |
| Key: FILEID_NAME_HASH |
| field: file_id |
| value: create_time |
| redis 語句 |
| hset key field value |
| hget key field |
`------------------------------------------*/
#define FILEID_TIME_HASH "FILEID_TIME_HASH"
/*------------------------------------------.
| 文件ID和文件URL對應表 (HASH) |
| Key: FILEID_URL_HASH |
| field: file_id |
| value: url |
| redis 語句 |
| hset key field value |
| hget key field |
`------------------------------------------*/
#define FILEID_URL_HASH "FILEID_URL_HASH"
/*------------------------------------------.
| 文件ID和文件所屬用戶對應表 (HASH) |
| Key: FILEID_USER_HASH |
| field: file_id |
| value: username |
| redis 語句 |
| hset key field value |
| hget key field |
`------------------------------------------*/
#define FILEID_USER_HASH "FILEID_USER_HASH"
/*--------------------------------.
| 文件類型 |
`--------------------------------*/
#define FILE_TYPE_BMP "1"
#define FILE_TYPE_ZIP "2"
#define FILE_TYPE_VEDIO "3"
#define FILE_TYPE_MEDIA "4"
#define EVENT_TYPE_TXT "5"
#define EVENT_TYPE_OTHER "6"
/*------------------------------------------.
| 文件ID和文件類型對應表 (HASH) |
| Key: FILEID_TYPE_HASH |
| field: file_id |
| value: file_type |
| redis 語句 |
| hset key field value |
| hget key field |
`------------------------------------------*/
#define FILEID_TYPE_HASH "FILEID_TYPE_HASH"
```
- 概要
- 1 分布式存儲fastDFS
- 1.1 fastDFS 通用介紹
- 1.2 fastDFS安裝和使用
- 1.3 基于fastDFS實現分布式
- 2 緩存數據庫redis快速搭建
- 2.1 環境安裝
- 2.2 redis數據類型
- 2.3 redis訂閱發布模式
- 2.4 redis事務
- 2.5 redis備份
- 3 redis詳細攻略
- 3.1 redis簡介
- 3.2 redis使用場景
- 3.3 redis基本操作
- 3.4 redis數據類型
- 3.4.1 字符串
- 3.4.2 HASH-字典
- 3.4.3 List-列表
- 3.4.4 Set-集合
- 3.4.5 Sorted Set-有序集合
- 3.4.6 訂閱-發布
- 3.4.7 事務
- 3.5 redis配置文件
- 3.6 持久化
- 3.7 redis性能測試
- 3.8 redis-C-API
- 3.9 redis-C++-API
- 3.10 總結與建議
- 4 memcache緩存數據庫
- 4.1 什么是memcached
- 4.2 memcached的特征
- 4.3 memcached的內存管理
- 4.4 如何使用memcached
- 4.5 memcached參數詳解
- 4.6 memcached安裝
- 4.7 memcached-C客戶端
- 4.8 memcached-C++客戶端
- 5 Nginx
- 6 FastCGI
- 6.1 CGI
- 6.2 FastCGI
- 6.3 Nginx與FastCGI
- 7 Nginx上部署fastDFS
- 8 項目概要
- 8.1 上傳文件功能
- 8.2 主界面顯示與下載文件功能
- 8.3 注冊功能
- 8.4 登陸功能
- 8.5 文件分類功能
- 8.6 個人網盤功能
- 8.8 秒傳功能