如何實現一個簡易的圖片上傳Web Server

MADAO是不會開花的發表於2019-04-10

一. 框架

選用express框架,文件

npm init

npm install express --save
複製程式碼

二. 簡單測試請求

在當前目錄新建index.js檔案

const express = require("express");

const app = express();

app.get("/", (req, res) => {
    res.send("Hello Node.js");
});

const port = 3000;
app.listen(port);
複製程式碼

在終端輸入: node index.js

在瀏覽器中開啟127.0.0.1:3000

如何實現一個簡易的圖片上傳Web Server

三.使用form上傳圖片

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>upload</title>
</head>
<body>
  <form action="http://127.0.0.1:3000/upload" method="post" enctype="multipart/form-data">
    <div>
      <input type="file" name="avatar" accept="image/*">
    </div>
    <input type="submit" value="上傳">
  </form>
</body>
</html>
複製程式碼

如何實現一個簡易的圖片上傳Web Server

將index.js中的介面更新成

app.post("/upload", (req, res) => {
  res.send('上傳成功')
});
複製程式碼

注意:index.js中的檔案只要改了,就要重新啟動服務

試著上傳一下:

如何實現一個簡易的圖片上傳Web Server

四. 將前端傳送的圖片儲存在伺服器中

這裡需要用到一個叫multer的庫

npm install multer --save

根據他的文件,改一下index.js:

const express = require("express");
const multer = require("multer");

// 這裡定義圖片儲存的路徑,是以當前檔案為基本目錄
const upload = multer({ dest: "uploads/" });
const app = express();
/* 
  upload.single('avatar') 接受以avatar命名的檔案,也就是input中的name屬性的值
  avatar這個檔案的資訊可以衝req.file中獲取
*/
app.post("/upload", upload.single("avatar"), (req, res) => {
  console.log(req.file);
  res.send("上傳成功");
});

const port = 3000;
app.listen(port);
複製程式碼

改完之後重新啟動服務,再重新上傳:

如何實現一個簡易的圖片上傳Web Server

可以看到req.file中就是上傳的檔案資訊。

同時,你會發現當前目錄下,會多一個資料夾叫uoloads。

如何實現一個簡易的圖片上傳Web Server

那個很長名字的檔案,就是剛剛前端傳的圖片。只要改一下字尾名就可以預覽了:

如何實現一個簡易的圖片上傳Web Server

五. 將儲存的圖片名返回給前端

一般上傳完頭像會有一個預覽功能,那麼只需要後端將上傳後的圖片名傳送給前端,前端重新請求一下圖片就好了,前面都是用form預設的提交,這個提交存在一個問題就是,提交完成後頁面會發生跳轉。所以現在一般都是用ajax進行上傳。

// js程式碼
upload.addEventListener('submit', (e) => {
  // 阻止form 的預設行為
  e.preventDefault();
  
  // 建立FormData物件
  var formData = new FormData();
  var fileInput = document.querySelector('input[name="avatar"]');
  formData.append(fileInput.name, fileInput.files[0]);
  
  // 建立XMLHttpRequest
  var xhr = new XMLHttpRequest();
  xhr.open('POST', upload.action);
  xhr.onload = function() {
    console.log(xhr.response)
  }
  xhr.send(formData);
})
複製程式碼
  • 小提示:如果HTML的元素有id屬性,那麼可以不用document.querySelector去選中它,可以直接使用,就像全域性變數一樣。
// index.js
app.post("/upload", upload.single("avatar"), (req, res) => {
  res.json({name: req.file.filename }); // 使用json格式返回資料。 
});

複製程式碼

這時候重新傳送,會出現一個問題:

如何實現一個簡易的圖片上傳Web Server

由於程式碼是寫在 JS Bin上的,使用AJAX請求不同域名的介面,會出現跨域情況,解決這個問題需要,在index.js中加上一個頭部,就是報錯資訊中的Access-Control-Allow-Origin

app.post("/upload", upload.single("avatar"), (req, res) => {
  res.set('Access-Control-Allow-Origin', '*'); 
  res.json({name: req.file.filename });
});
複製程式碼
  • *表示所有其他域名都可訪問,也可以將*改為其他允許的域名。

重新傳送:

如何實現一個簡易的圖片上傳Web Server

這樣成功的上傳了圖片,並且拿到了上傳後的圖片名。

這裡可以使用一個庫cors,來完成新增響應頭的操作:

npm install cors --save

修改index.js

const express = require("express");
const multer = require("multer");
const cors = require('cors');  // 新增
// 這裡定義圖片儲存的路徑,是以當前檔案為基本目錄
const upload = multer({ dest: "uploads/" });
const app = express();

app.use(cors());  // 新增
/* 
  upload.single('avatar') 接受以avatar命名的檔案,也就是input中的name屬性的值
  avatar這個檔案的資訊可以衝req.file中獲取
*/
app.post("/upload", upload.single("avatar"), (req, res) => {
  res.json({name: req.file.filename });
});

const port = 3000;
app.listen(port);

複製程式碼

五. 展示上傳後的圖片

新定義一個介面:

app.get("/preview/:name", (req, res) => {
  res.sendFile(`uploads/${req.params.name}`, {
    root: __dirname,
    headers:{
      'Content-Type': 'image/jpeg',
    },
  }, (error)=>{
    if(error){
      res.status(404).send('Not found')
    }
  });
});
複製程式碼

/preview:name這種方式定義介面的路徑,請求過來的時候,就可以從req.params.name中拿到/preview/xxxx中的xxxx了。

修改下HTML:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <form id="upload" action="http://127.0.0.1:3000/upload" method="post" enctype="multipart/form-data">
    <div>
      <input type="file" name="avatar" accept="image/*">
    </div>
    <input type="submit" value="上傳">
  </form>
  <img src="" id="avatarImg">  <!-- 新增 -->
</body>
</html>
複製程式碼

改下js

upload.addEventListener('submit', (e) => {
  // 阻止form 的預設行為
  e.preventDefault();
  
  // 建立FormData物件
  var formData = new FormData();
  var fileInput = document.querySelector('input[name="avatar"]');
  formData.append(fileInput.name, fileInput.files[0]);
  
  // 建立XMLHttpRequest
  var xhr = new XMLHttpRequest();
  xhr.open('POST', upload.action);
  xhr.onload = function() {
    var imgName = JSON.parse(xhr.response).name;  // 新增
    avatarImg.setAttribute('src', 'http://127.0.0.1:3000/preview/' + imgName); // 新增
  }
  xhr.send(formData);
})
複製程式碼

結果:

如何實現一個簡易的圖片上傳Web Server

六. 將程式碼部署到Heroku

Heroku是一個支援多種程式語言的雲平臺即服務。最重要的它是免費的。這是他的官方網站Heroku,注意不科學上網的話,可會超級慢或者進不去。而且科學上網要全域性模式..

  1. 註冊,過程省略
  2. 選擇建立一個新的應用

如何實現一個簡易的圖片上傳Web Server

  1. 在部署的時候,有三個選擇,我選擇選擇GitHub

  2. 由於選擇GitHub,那麼還需要建立一個倉庫,把程式碼放上去。

  3. 放上去之間還要改一下程式碼:

    因為部署是交給heroku的,所以埠號不能寫死:

    const port = process.env.PORT || 3000;
    複製程式碼
  4. 在package.json新增一個npm start命令

    "start": "node index.js"

  5. 在GitHub上建立倉庫並上傳程式碼,過程略,別忘了寫.gitignore檔案

  6. 這是我的倉庫地址

  7. 在heroku中選擇倉庫並且選擇分支master,部署

如何實現一個簡易的圖片上傳Web Server

  1. 預覽

如何實現一個簡易的圖片上傳Web Server

如何實現一個簡易的圖片上傳Web Server

這個就是部署好的域名了。

用這個域名試一試

如何實現一個簡易的圖片上傳Web Server

大功告成。可惜的就是heroku得科學上網才行。

相關文章