為什麼要在 n8n 使用 Reply 模式發送圖文?
在開發 LINE 機器人自動化流程(n8n)時,當我們收到使用者傳來的訊息並需要即時回覆時,最推薦且標準的方式就是採用 LINE 的 Reply 模式(回覆機制) 。
使用 Reply 模式的核心優勢在於:它是完全免費的! 無論你回覆多少次訊息,都不會扣除 LINE 官方帳號每月的主動推播(Push)額度 。
然而,在 Reply 模式下處理圖文回覆時,常會面臨一個現實問題:「有時想回傳圖片加文字,有時卻只想回傳純文字。」 如果硬把空字串傳給 LINE 的圖片 API,會直接跳出 400 Bad Request 錯誤 ;而文字裡的「換行符號」也非常容易造成 JSON 語法崩潰(跳出 Bad control character 錯誤) 。
這篇文章將教你如何在 n8n Reply 模式下,用單一 HTTP Request 節點優雅且動態地判斷要發送純文字還是圖文訊息,並徹底解決 JSON 換行字元報錯的痛點 !
Reply 模式下自動判斷並完美呈現圖文訊息
在 Reply 模式下,必須透過 Webhook 取得 LINE 傳來的 replyToken 。透過這套設定,無論前一個節點傳進來的是「圖片+文字」還是「只有文字」,n8n 都能自動組裝出符合 LINE Reply API 規範的標準 Payload 。
當同時有圖片與文字時,Reply Message API 輸出的 JSON 格式如下 :
{
"replyToken": "replyToken代碼",
"messages": [
{
"type": "image",
"originalContentUrl": "圖片網址",
"previewImageUrl": "圖片網址"
},
{
"type": "text",
"text": "測試文字"
}
]
}
效果說明:LINE 會將換行符號 \n 正確渲染為手機上的多行文字 ,且圖片與文字會在同一次 Reply API 請求中順暢呈現,完全不浪費任何訊息費用 !
三步驟搞定 n8n Reply 設定
步驟 1:設定 Reply 專用 Endpoint 與 Authentication
1.選擇 Reply API Endpoint: 請務必選用 Reply Message API,網址為:
POST https://api.line.me/v2/bot/message/reply (特別強調:replyToken 為一次性且有時效性,必須從 LINE Webhook 觸發事件中取得 !)
2憑證套用(Authentication):
建議直接將 LINE 的 Channel Access Token 設定在 n8n 的 Credentials 中(選擇 Header Auth) 。這樣可以避免 Token 在 HTTP Request 節點中明碼暴露 ,未來更換金鑰時也方便集中管理 。
步驟 2:解決最棘手的「JSON 解析錯誤」
在文字訊息中,如果包含換行(Enter)或特殊字元,直接放入 JSON 常會引發:
Bad control character in string literal in JSON 錯誤 。
解決祕訣:使用 JavaScript 的 JSON.stringify() 來處理字串 ,它會自動幫你轉義所有換行符號與特殊字元 !
- 正確寫法(注意:
JSON.stringify外圍不需要再加雙引號"") :
"text": {{ JSON.stringify($json['訊息']) }}
步驟 3:用 IIFE 動態組合 Reply 的 messages 陣列(核心關鍵!)
為了讓「沒圖片時」不會因為空字串導致 Reply API 報錯 ,我們可以在 HTTP Request 節點的 JSON Body 欄位中,加入一段 JavaScript 的 IIFE(立即執行函數)來動態判斷並組裝訊息 :
請將 HTTP Request 節點的 JSON Body 替換為以下內容 :
{
"replyToken": "{{ $json.replyToken }}",
"messages": {{
(() => {
const messages = [];
const textVal = $json['訊息'];
const imgUrl = $json.line_image_url;
// 1. 檢查圖片:網址存在且非空字串時,才加入圖片物件
if (imgUrl && imgUrl.trim() !== '') {
messages.push({
"type": "image",
"originalContentUrl": imgUrl,
"previewImageUrl": imgUrl
});
}
// 2. 檢查文字:文字存在且非空字串時,才加入文字物件
if (textVal && textVal.trim() !== '') {
messages.push({
"type": "text",
"text": textVal
});
}
// 3. 備援機制:若兩者皆無,給予預設文字避免 Reply API 報錯
if (messages.length === 0) {
messages.push({
"type": "text",
"text": "收到您的訊息!"
});
}
return JSON.stringify(messages);
})()
}}
}
💡 ** Reply 模式小貼士**:
- 時效控制:因為
replyToken在收到 Webhook 後很快就會過期,請確保你的 n8n 流程能迅速執行完畢(避免在 Reply 之前加入過長的等待或耗時過久的大模型 AI 處理) 。 - 圖片權限:如果圖片儲存在 Google Drive 等雲端硬碟,請務必確認檔案已設定為**「知道連結的人皆可檢視」**的公開權限,否則 LINE 伺服器抓不到圖片,手機端會顯示破圖喔 !