分析(直接實踐是最好的。。。。。):
一、Ningx 上傳(
1.安裝Nginx 的模塊文件(upload):https://www.nginx.com/resources/wiki/modules/upload/,默認Nginx 肯定是沒安裝這個擴展模塊的,你可以准備刪除Nginx重新去官網下載一個最新穩定版本,並且進行編譯吧。。。。。。
# Upload form should be submitted to this location
location /upload {
# Pass altered request body to this location
upload_pass /upload.php;
# Store files to this directory
# The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
這里是扔到10個文件夾里去
upload_store /usr/share/nginx/html/file 1;
# Allow uploaded files to be read only by user
upload_store_access user:r;
就是在這里,他會自動給你命名。
# Set specified fields in request body
upload_set_form_field "${upload_field_name}_name" $upload_file_name;
upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;
upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;
# Inform backend about hash and size of a file
upload_aggregate_form_field "${upload_field_name}_md5" $upload_file_md5;
upload_aggregate_form_field "${upload_field_name}_size" $upload_file_size;
upload_pass_form_field "^submit$|^description$";
}
這里是個大坑,因為如果默認就是當前的服務器的80端口,配置這個是會出錯的,我就直接沒用代理,直接
upload_pass /upload.php;
#如果是當前端口,設置proxy_pass會出現錯誤
# Pass altered request body to a backend
#location @test {
# proxy_pass htpp://127.0.0.1;
#}
2.Nginx的某個路由(看我下面的配置文件)檢測到上傳請求后,會分別將各個你定義的form file name,上傳到不同的文件夾,一共是10個(創建10個文件夾,命名0 1 2 3 ...),文件位置自定義(但一定要包含那10個文件夾,這個切記),一定要檢測你創建的文件夾Nginx是否具有寫入權限,這個可以自己看log(這個相當重要),如果你配置完成后想玩點新花樣,可以自己玩玩,還可以限制上傳速度之類的,而且可以做轉發,如果你配置的代理服務器本身就做了URL反向代理,那肯定可以轉發上傳文件到多個Nginx服務器(上傳文件提交信息,比如文件位置在哪兒之類的。)去滴。。。
二、直接PHP上傳
PHP上傳文件,本身就要配置Nginx 模塊,所以很多人會搞混,其實兩者是有差異的,
正常的上傳流程:html 提交上傳文件,nginx 收到后 扔到tmp目錄,PHP收到后,把TMP的上傳文件扔到自己想放的文件夾。
-------------------------------------------------------------------
兩者都需要編寫HTML,直接提交給Nginx ,在Upload Modules 配置好了,是可以直接接受多個文件上傳的。
<!-- 這是提交給nginx -->
<html lang="CN">
<head>
<meta charset="UTF-8">
<title>Test upload</title>
</head>
<body>
<h2>Select files to upload</h2>
<form enctype="multipart/form-data" action="/upload" method="post">
<input type="file" name="file"><br>
<input type="file" name="file1"><br>
<input type="file" name="file2"><br>
<input type="submit" name="submit" value="Upload">
<input type="hidden" name="test" value="value">
</form>
</body>
</html>
<!-- 這是直接提交給php -->
<html lang="CN">
<head>
<meta charset="UTF-8">
<title>Test upload</title>
</head>
<body>
<h2>Select files to upload</h2>
<form enctype="multipart/form-data" action="/upload.php" method="post">
<input type="file" name="file"><br>
<input type="submit" name="submit" value="Upload">
<input type="hidden" name="test" value="value">
</form>
</body>
</html>
1:通過配置Ningx 安裝 Upload Modules 進行 文件上傳 再從PHP 接受 Ningx POST過來的參數。
2.直接通過編寫PHP,從HTML 負責文件上傳
server {
listen 80;
server_name localhost;
charset utf-8;
access_log /usr/local/nginx/logs/access.log main;
client_max_body_size 100m;
# Upload form should be submitted to this location
location /upload {
# Pass altered request body to this location
upload_pass /upload.php;
# Store files to this directory
# The directory is hashed, subdirectories 0 1 2 3 4 5 6 7 8 9 should exist
upload_store /usr/share/nginx/html/file 1;
# Allow uploaded files to be read only by user
upload_store_access user:r;
# Set specified fields in request body
upload_set_form_field "${upload_field_name}_name" $upload_file_name;
upload_set_form_field "${upload_field_name}_content_type" $upload_content_type;
upload_set_form_field "${upload_field_name}_path" $upload_tmp_path;
# Inform backend about hash and size of a file
upload_aggregate_form_field "${upload_field_name}_md5" $upload_file_md5;
upload_aggregate_form_field "${upload_field_name}_size" $upload_file_size;
upload_pass_form_field "^submit$|^description$";
}
#如果是當前端口,設置proxy_pass會出現錯誤
# Pass altered request body to a backend
#location @test {
# proxy_pass htpp://127.0.0.1;
#}
location / {
root /usr/share/nginx/html/work/public;
index index.html index.htm index.php;
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
root /usr/share/nginx/html/work/public;
fastcgi_pass unix:/opt/remi/php70/root/run/lock/php-fcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 15d;
}
location ~ .*\.(js|css)?$
{
expires 1d;
}
}
自己感受~~~~~
然后貼上Demo PHP 代碼:
<?php
header('Content-Type: text/html;charset=UTF-8');
//文件后綴=>文件類型
$type = ['.pdf' => 'application/pdf'];
const FILE_DIR = '/usr/share/nginx/html/work/';
//如果非nginx upload module 上傳文件
if (count(($file = $_FILES['file'])) > 0) {
if ($file['error'] == 0) {
//判斷文件類型是否存在,文件后綴是我們自己的key去定義
if ($fileType = array_search($file['type'], $type)) {
//以當前的時間命名目錄
$date_dir = date('Y-m-d', time());
//如果目錄沒創建,我們就自己創建一個
if (!is_dir(FILE_DIR . $date_dir)) {
if (!mkdir(FILE_DIR . $date_dir)) {
return header('location:503.html');
}
}
//文件的MD5+當前unix時間戳+一個5位隨機數,如果此處需求頻繁也可以用微秒時間戳
$filename = FILE_DIR . $date_dir . '/' . (md5_file($file['tmp_name']) . time() . rand(9999, 99999)) . $fileType;
//生成新的文件
if (rename($file['tmp_name'], $filename)) {
return header('Location: success.html');
}
}
}
switch ($file['error']) {
case 1:
http_response_code(400);
exit('文件大小超出了服務器的空間大小');
case 2:
http_response_code(400);
exit('要上傳的文件大小超出瀏覽器限制');
case 3:
http_response_code(400);
exit('文件僅部分被上傳');
case 4:
http_response_code(404);
exit('沒有找到要上傳的文件');
case 5:
http_response_code(503);
exit('服務器臨時文件夾丟失');
case 6:
http_response_code(503);
exit('文件寫入到臨時文件夾出錯');
}
}
//如果是nginx upload module
if (count(($file = $_POST)) > 0) {
//判斷文件類型是否存在,文件后綴是我們自己的key去定義
if ($fileType = array_search($file['file_content_type'], $type)) {
//以當前的時間命名目錄
$date_dir = date('Y-m-d', time());
//如果目錄沒創建,我們就自己創建一個
if (!is_dir(FILE_DIR . $date_dir)) {
if (!mkdir(FILE_DIR . $date_dir)) {
return header('location:503.html');
}
}
//文件的MD5+當前unix時間戳+一個5位隨機數,如果此處需求頻繁也可以用微秒時間戳
$filename = FILE_DIR . $date_dir . '/' . (md5_file($file['file_path']) . time() . rand(9999, 99999)) . $fileType;
//生成新的文件
if (rename($file['file_path'], $filename)) {
return header('Location: success.html');
}
}
}
http_response_code(400);
exit('錯誤操作方式!');
