ufserver文件上傳服務器-用來管理你項目中的圖片-性能可比Java、Python高十倍不止

大家在做項目的時候如果是web項目,項目又不大的情況下上傳圖片一般都是上傳到項目的webapp目錄下面,webapp下面會有一個upload的文件夾,今天給大家分享的是在項目中如何把圖片上傳到其他服務器,由於java比較笨重,故我用GO語言寫了一個小型的上傳文件的服務,下面給大家講解具體怎麼使用。

微雲鏈接:鏈接:https://share.weiyun.com/5Uqsa4l 密碼:9wpied

下載後是一個ufserver.exe文件,打開cmd,在命令行中執行ufserver.exe 就可以了,或者直接雙擊運行。執行成功如下:

如上界面,就一定啓動成功啦。

下面附上一個測試的html文件。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="http://localhost:9876/upload" enctype="multipart/form-data" method="post">
			<input type="file" name="upload-file" />
			<input type="submit" value="提交" />
		</form>
		
	</body>
</html>

默認的端口是9876,當然你也可以在配置文件中修改成自己的端口,配置文件下面會詳細講,

這是上傳成後返回的信息如下:

{
    "absolutePath": "http://192.168.0.103:9876/2019/09/06/150405-B7z3v113.jpg",
    "createTime": "2019-09-06T11:58:42.0186458+08:00",
    "fileSize": 3047,
    "msg": "successfully",
    "originalFileName": "2.jpg",
    "relativePath": "/2019/09/06/150405-B7z3v113.jpg",
    "statusCode": 200,
    "thums": [
        "http://localhost:9876/2019/09/08/150405-kj0s66Xa_200_200_3.png"
        "http://localhost:9876/2019/09/08/150405-kj0s66Xa_120_120_3.png"
    ]  //>= v6版本中新增,縮略圖
}

一些具體的信息都在裏邊,有絕對路徑,相對路徑,源文件名等,大家注意了,一般數據庫裏邊保存的相對路徑哦,千萬不要保存絕對路徑,除非是富文本編輯器裏邊上傳圖片的時候會保存成絕對路徑。不過後面如果靜態資源遷移,那就是災難性的。

上面已經演示瞭如何上傳,下面我們來說說它具體的配置。

第一次運行只會生成static目錄,logs目錄爲服務的請求日誌,cfg.json是配置文件,默認可以不需要cfg.json,可以直接運行

cfg.json具體配置如下:

{
  "url":"http://localhost",   //url爲訪問的路徑,如果不是本電腦,可以配置其他IP或者域名  
  "port":9876,   //訪問的端口,默認爲9876
  "indexFolder":true,  //是否開啓目錄索引,默認爲true
  "logEnable":true   //是否開啓訪問日誌,默認爲false,
  "staticDirs":["xxx","D:\\tmp\\vvv"], //v2版本中新增
  "rewriteUrls": [
       {"/resource":"img"}
    ],  //v3新增
  "defStaticDir":"static", //默認文件存放的目錄爲static目錄
  "enableRate":false, //是否開啓限流,開啓後默認爲1s/10000
  "capacity":10000,  //限流採用令牌桶算法,桶的容量
  "rate":10000,    //限流採用令牌桶算法,每秒的速率,建議和capacity一樣
  "tempPartDir":"C:\\users\\xx", 分片上傳時臨時文件目錄,默認爲用戶的TMP目錄
  "isDelSearchDir": false, // v9新增 刪除的時候是否開去多目錄檢索
  "delSearchDir":["img","static"] // v9新增 刪除文件要檢索哪些目錄,會去這些文件夾下找對應的文件刪除
  "webHookEnabled": false, // v10版本新增 啓用webhook
  "webHookUrl": "http://localhost:9876/webhook",  // v10版本新增 webhook地址,默認POST請求
  "encrypt":false,  //[>=v11]是否開啓訪問效驗
  "encryptSalt":"abcdefg1234567a1b2c3d4f5g6",  //[>=v11]效驗混合加密鹽值
  "encryptMethod":"md5",  //[>=v11]加密方式
  "encryptType":"dynamic" //[>=v11] dynamic 、 server  ,默認dynamic類型
  "encryptUrl" : "http://www.xxxxx.com/vs" //[>=12] 驗證sign的url,一般爲應用服務器自己的
}

////////////staticDirs參數說明///////////////////
假如您現在的根目錄是 D:/tmp,upload-server啓動後會生成D:/tmp/static,staticDirs可以讓ufserver增加搜索目錄,數組中的xxx是相對D:/tmp目錄,數組裏邊可以傳相對路徑,也可以傳絕對路徑。
假如有xxx目錄下有aa.js ,vvv目錄下面bb.js ,那麼在瀏覽器中訪問http://localhost:9876/aa.js去會xxx
目錄下查找,訪問bb.js會去vvv目錄下面查找,數組中越靠前優先級越大。

//////////////////rewriteUrls參數說明//////////////
rewriteUrls是一個數組,數組裏邊是map,鍵值對形式,他的作用主要是用來url重寫,現在配置的有
/resource,img 意思是當我訪問/resource/xxx.js 的時候,upload-server會去img目錄下面找xxx.js
訪問/resource/js/jq.js 會去img目錄下面的js目錄找jq.js


//////////////////encrypt參數說明//////////////
encrypt表示是否開啓效驗模式,如果開啓後,默認會攔截/upload和/delete請求,會對請求進行判斷是否帶有加密後的sign值。
效驗需要參數
-randomstr(隨機字符串)
-timestamp(unix時間戳10爲)
-sign(加密後的值)
客戶端在上傳的時候需要把這個三個值在URL參數中傳過來,其中randomstr建議生成uuid,
保證每次不一致,timestamp爲時間戳,但是不是當前時間的時間戳,比如說當前的這個sign值有效期是3分
鍾,那麼timestamp就是3分鐘後的時間戳,sign是在應用服務器的服務端加密後的值,sign的加密方式爲:
String result = sign+randomstr+timestamp+salt
在對result進行ASCII按從小到大的順序排序,把排序後的結果進行md5加密
注意上面提到的salt值是在ufserver配置文件中配置,在應用服務器中保存一份,不可泄露。
/upload?sign=61f93003d3b104876558b7064a0ce40b&randomstr=sdf
&timestamp=1569826200
====================ufserver處理結果如下=======================
 timestamp:1569826200 
 sign:61f93003d3b104876558b7064a0ce40b 
 salt:abcdefg1234567a1b2c3d4f5g6 
 method:md5 
 encryptStr:00111222233445556666789aabbccdddefffggs 
 result:5e269c3040a6c16d038a9b9e79719b45 
從這個結果中我們可以看到,客戶端傳過來的是 timestamp、randomstr在加上配置的salt,排序後的結果
爲encryptStr,在用encryptStr進行md5加密,加密後的值和傳過的sign值進行比對,如果一致,就通過。如果返回錯誤信息。


//////////////////encryptUrl參數說明//////////////
encryptType如果爲server的時候,說明客戶端傳過來的sign,ufserver會回調encryptUrl並且帶上sign參
數和action類型,去請求應用服務器,由應用服務器驗證並且返回狀態,如果成功返回字符串successfully,
如果sign已經失效,返回非successfully就可以。
server的驗證模式爲應用服務器生成sign值,sign可以是UUID也可以是其他信息加密而成返回給客戶端,客戶
端上傳文件到ufserver的時候,在url後面帶上sign值,ufserver接受到後會以POST請求去請求在ufserver
中配置的encryptUrl,並會在encryptUrl後面以問號參數拼接sign值還有action請求,應用服務器收到後驗
證sign是否有效,並且返回對應的狀態值。


//////////////////encryptType參數說明//////////////
dynamic:動態加密,可以設置過期時間,一併傳遞給ufserver,調試相對來說麻煩一些,ufserver參與
加密,按照一定的加密方式來加密驗證。
server:服務器驗證加密,應用服務器生成sign傳遞給客戶端,客戶端傳遞給ufserver,ufserver發起
回調URL去應用服務器驗證,ufserver不參與驗證,全部交給應用服務器。


//////////////////IsDelSearchDir參數說明//////////////
如果IsDelSearchDir爲true,返回的格式爲

{
    "msg": "successfully",
    "notFiles": [
        "img:/2019/09/21/150405-16237U35.png",
        "static:/2019/09/21/150405-16237U35.png"
    ],
    "statusCode": 200,
    "successs": [
        "img:/2019/09/21/150405-7914ZGwv.png"
    ]
}

如果IsDelSearchDir爲false,返回的格式爲

{
    "msg": "successfully",
    "notFiles": [
    ],
    "statusCode": 200,
    "successs": [
        "/2019/09/21/150405-7B3ZxiR5.png"
    ]
}

如果文件在對應的目錄下沒有找到,則在notFiles中返回,刪除成功會在successs中返回。
如果開啓多目錄檢索,"img:/2019/09/21/150405-16237U35.png",會在前面加目錄名,如果未開啓,直接
返回對應的路徑。

URL參數詳解

上傳文件的URL爲:/upload

[URL可選參數]
  filePath  -- 如果自定義路徑的話可以傳這個參數,格式爲 image/xxxx ,不以斜槓開頭哦
  sign  [>=12] --  (可選)加密參數值
  rename    -- 是否需要重命名,默認爲true,建議爲true
  cfname[>=v8]   -- 自定義文件名稱,比如文件上傳後名稱爲 xxx.jpg
  thum  [>=v6] -- 是否需要生成縮略圖,參數爲true和false,默認爲false
  async [>=v6] -- 生成縮略圖異步生成還是同步執行,默認爲true,經測試1s能生成>1000張以上的縮略圖
  mode  [>=v6] -- 生成縮略圖模式,參數有1、2、3,2爲調整大小,會縮放圖片,1和3位裁剪和等比縮放,具體可以傳不同的參數來看效果
  q     [>=v6] -- 生成縮略圖的參數,傳參形式爲:width,height或者width,height|width,height,例如
http://localhost:9876?thum=true&q=300,200這個url會成300*200大小的縮略圖,
http://localhost:9876?thum=true&q=300,200|500,600會生成2個縮略圖,分別是300*200和500*600
http://localhost:9876?thum=true&q=300,200|500,600|xx,xx|xx,xx 可以生成多重
http://localhost:9876?thum=true&q=300|500|xx|如果是正方形,可以傳一個參數
http://localhost:9876?thum=true&q=300,0|200,0高度傳0會按照寬度等比縮放

**cfname自定義名稱必須要在rname=true的情況下才生效哦**

---------------------------------------------------

分片上傳URL爲:/upload/part

[URL可選參數]
  filePath -- 如果自定義路徑的話可以傳這個參數,格式爲 image/xxxx ,不以斜槓開頭哦
  rname    -- 是否需要重命名,默認爲true,建議爲true
  cfname   -- 自定義文件名稱,比如文件上傳後名稱爲 xxx.jpg
  rpart    -- 是否需要對part文件進行檢測重寫,建議爲false
  sign  [>=12] 加密參數值
  
 [POST參數]
   fileId -- 文件ID,必傳,由客戶端保持唯一,可以使用UUID,ufserver根據fileId來生成臨時目錄
   chunks -- 分塊數,總共有多少個塊  採用webuploader 參數引用
   chunk  -- 當前的塊索引,採用webuploader 參數引用
   size   -- 文件的大小字節數

 [分配上傳成功後返回結果]
 
  {
    absolutePath: "http://localhost:9876"
    createTime: "2019-09-10T14:25:49.90321+08:00"
    fileSize: 3000000
    msg: "part successfully"
    originalFileName: "syncthing-windows-amd64-v1.2.1.zip"
    relativePath: ""
    statusCode: 200
    thums: null
  }

[最後一個分片上傳成功後返回結果]

  {
    absolutePath: "http://localhost:9876/doc/stn.zip"
    createTime: "2019-09-10T14:25:50.5484782+08:00"
    fileSize: 404187
    msg: "successfully"
    originalFileName: "syncthing-windows-amd64-v1.2.1.zip"
    relativePath: "/doc/stn.zip"
    statusCode: 200
    thums: null
  }


---------------------------------------------------

刪除文件URL爲:/delete

[URL可選參數]
  fp[>=v9]  -- 要刪除文件的相對路徑,上傳成功後返回的相對路徑,如果要刪除多個,用逗號分隔,比如
http://localhost:9876/delete?fp=/2019/09/21/150405-7B3ZxiR5.png,/2019/09/21/150405-7B3ZxiR2.png
http://localhost:9876/delete?fp=/2019/09/21/150405-7B3ZxiR5.png

各種URL效果圖如下:https://blog.csdn.net/qq_24434671/article/details/100625771

大家可能對目錄索引不太瞭解,下面我們來看一下,不開啓目錄索引的情況下,訪問http://localhost:9876,如下:

會出現拒絕訪問,下面我們開啓目錄索引在訪問:

可以看到出來了2019,這個2019是怎麼來的呢,是static中的目錄,static下面有多少目錄,在這裏都會一一列舉出來,大家如果在apache網站上下載過一些jar包之類的,應該就對這類目錄索引很熟悉了。

默認上傳文件後保存的路徑是   yy/mm/dd/hhmmss-8位隨機數.後綴

如果想自定義路徑怎麼辦呢,可以這麼做:

在form中上傳的url後面加參數

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="http://localhost:9876/upload?filePath=static/img/2019" enctype="multipart/form-data" method="post">
			<input type="file" name="upload-file" />
			<input type="submit" value="提交" />
		</form>
		
	</body>
</html>

在URL後面可以通過filePath參數去傳自定義目錄http://localhost:9876/upload?filePath=static/images/2019,發現有filepath參數後程序會自動創建你傳過的目錄路徑,注意,這裏的filePath的路徑是相對於static目錄的,就是啓動程序後會生成static目錄,你傳的不管目錄是什麼,最後都會在static目錄下面創建相對目錄。如果傳的是上面的路徑,最後在static目錄下面生成的目錄結構爲

static/static/images/2019

如果不傳filePath的話,那麼就採取默認的路徑規則。

關於自定義文件名

細心的同學可能發現上傳後的文件名都是經過重新編制的,那麼有些情況下我就想上傳原來的文件名並且讓程序不要修改,怎麼做呢,其實可以在url後面加rename=false參數,具體如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<form action="http://localhost:9876/upload?rename=false" enctype="multipart/form-data" method="post">
			<input type="file" name="upload-file" />
			<input type="submit" value="提交" />
		</form>
		
	</body>
</html>

這樣一來的話上傳的時候是什麼文件名,返回的就是什麼文件名稱了,不過這樣不建議用,因爲如果文件重複的話會進行覆蓋,比較危險,不建議這樣去傳。

關於WebUploader上傳案例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<link rel="stylesheet" type="text/css" href="css/webuploader.css" />
		<script type="text/javascript" src="js/jquery.js"></script>
		<script type="text/javascript" src="js/webuploader.min.js"></script>
	</head>
	<body>
		<div id="uploader" class="wu-example">
			<!--用來存放文件信息-->
			<div id="thelist" class="uploader-list"></div>
			<div class="btns">
				<div id="picker">選擇文件</div>
			</div>
		</div>
		<script>
			var uploader = WebUploader.create({
				auto:true,
				// swf文件路徑
				swf:'js/Uploader.swf',

				// 文件接收服務端。
				server: 'http://localhost:9876/upload',
				/* fileVal:"upload-file", */
				fileVal:"upload-file",
				// 選擇文件的按鈕。可選。
				// 內部根據當前運行是創建,可能是input元素,也可能是flash.
				pick: '#picker',

				// 不壓縮image, 默認如果是jpeg,文件上傳前會壓縮一把再上傳!
				resize: false
			})
			uploader.on( 'uploadSuccess', function( file ) {
			   console.log(file)
			});
		</script>
	</body>
</html>

可以看到,上傳成功了。

關於WebUploader分片上傳案例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<link rel="stylesheet" type="text/css" href="css/webuploader.css" />
		<script type="text/javascript" src="js/jquery.js"></script>
		<script type="text/javascript" src="js/webuploader.min.js"></script>
	</head>
	<body>
		<div id="uploader" class="wu-example">
			<!--用來存放文件信息-->
			<div id="thelist" class="uploader-list"></div>
			<div class="btns">
				<div id="picker">選擇文件</div>
			</div>
		</div>
		<script>
			var uploader = WebUploader.create({
				auto:true,
				// swf文件路徑
				swf:'js/Uploader.swf',

				// 文件接收服務端。
				server: 'http://localhost:9876/upload/part?filePath=doc&rname=false&cfname=stn.zip',
				/* fileVal:"upload-file", */
				fileVal:"upload-file",
				// 選擇文件的按鈕。可選。
				// 內部根據當前運行是創建,可能是input元素,也可能是flash.
				pick: '#picker',
				
				chunked:true, //開啓分配上傳
				chunkSize:3000000, //默認1M
				chunkRetry:2, //允許自動重試的次數
				threads:3, //上傳的併發數
				formData:{"fileId":"xvvx"},

				// 不壓縮image, 默認如果是jpeg,文件上傳前會壓縮一把再上傳!
				resize: false
			})
			uploader.on( 'uploadSuccess', function( file,resp ) {
			   console.log(file,resp)
			});
			
			// 文件上傳過程中創建進度條實時顯示。
			uploader.on( 'uploadProgress', function( file, percentage ) {
				console.log(file,percentage)
			});
			
		</script>
	</body>
</html>
chunked:true, //開啓分配上傳
chunkSize:3000000, //默認1M
chunkRetry:2, //允許自動重試的次數
threads:3, //上傳的併發數
formData:{"fileId":"xvvx"},

可以看到,比較重要的就是這幾個配置了,前面四個用於開啓和配置webuploader的分片上傳

 

可以看到,我上傳了一個將近10M左右的,webuploader自動分成了四個分片,瀏覽器發了8個請求,其中四個是options請求,四個是POST請求,(截圖只截了個七個請求),瀏覽器把10M的文件分成四次分別提交給ufserver,ufserver收到後會在臨時目錄下爲每個chunk創建一個文件,最後把各個小文件合併成一個大文件。 

關於ufserver的命令行參數

在命令行輸入 ufserver.exe  --help

可以看到上面有幾個參數選項,

  • -sp 是source path
  • -dp 是 dpath,生成縮略圖後保存的文件名(全路徑哦)
  • -w  寬度
  • -h  高度
  • -m 模式

以上的選項是在生成縮略圖的時候需要用到,注意,如果只傳-sp 的話,那麼生成後的縮略圖的路徑是和sp在同目錄下,命名是原文件名_w_h.後綴

  • -s start  用於啓動服務器
  • -v 查看當前的版本號

關於用Java代碼上傳文件到ufserver

需要用到jar包如下:

  • org.apache.httpcomponents:httpclient:4.5.3
  • org.apache.httpcomponents:httpmime:4.5.3

jar包微雲地址如下:鏈接:https://share.weiyun.com/5Lz7Ego 密碼:j5rqgz

pom文件依賴:

<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.5.3</version>
</dependency>

<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpmime</artifactId>
	<version>4.5.3</version>
</dependency>

Java上傳代碼如下:

import java.io.File;
import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

public class UploadTest {

	public static void main(String[] args) {
		
		String URL = "http://localhost:9876/upload";
		String filePath = "C:\\Users\\xxx\\Desktop\\HW\\tp\\TCP.png";
		System.out.println(upload(URL,filePath));
	}

	/**
	 * 上傳文件
	 */
	public static String upload(String url,String filePath) {
		String res = "";
		CloseableHttpClient httpclient = HttpClients.createDefault();
		try {
			HttpPost httppost = new HttpPost(url);

			RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000)
					.build();
			httppost.setConfig(requestConfig);

			FileBody bin = new FileBody(new File(filePath));
			StringBody comment = new StringBody("This is comment", ContentType.TEXT_PLAIN);

			//這裏的name值爲upload-file
			HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("upload-file", bin)
					.addPart("comment", comment).build();

			httppost.setEntity(reqEntity);

			System.out.println("executing request " + httppost.getRequestLine());
			CloseableHttpResponse response = httpclient.execute(httppost);
			try {
				System.out.println(response.getStatusLine());
				HttpEntity resEntity = response.getEntity();
				if (resEntity != null) {
					String responseEntityStr = EntityUtils.toString(response.getEntity());
					System.out.println(responseEntityStr);
					res = responseEntityStr;
					System.out.println("Response content length: " + resEntity.getContentLength());
				}
				EntityUtils.consume(resEntity);
			} finally {
				response.close();
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				httpclient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return res;
	}
}

控制檯結果如下:

executing request POST http://localhost:9876/upload HTTP/1.1
HTTP/1.1 200 OK
{"absolutePath":"http://localhost:9876/2019/09/20/150405-43ehh0Sb.png","createTime":"2019-09-20T16:44:20.0764262+08:00","fileSize":233095,"msg":"successfully","originalFileName":"TCP.png","relativePath":"/2019/09/20/150405-43ehh0Sb.png","statusCode":200,"thums":null}
Response content length: 267

上面說了這麼多,如果您是一般使用,沒有特殊要求的話就不需要cfg.json文件,直接把ufserver下載下來運行就行。不需要其他的配置。上傳文件時候的name名稱是upload-file

上面就是關於ufserver.exe全部的配置和使用方式了,如果您在使用中有什麼問題的話可以在評論區留言哦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章