You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Twilio的图片收发与存储方案咨询(Python实现)

最经济的Twilio图片接收、存储与合并回传方案

一、存储方案:别折腾自建Dropbox,免费云存储足够

完全没必要搭建Dropbox这类服务,新手直接用免费对象存储就行,成本几乎为0还省心:

  • 首推Cloudflare R2:无出站带宽费(多数云存储下载会收带宽费,R2免这个),免费给10GB存储,存手机发送的图片绝对够用,配置也简单。
  • 备选AWS S3免费层:15GB存储+每月一定免费流量,个人使用完全覆盖,注意别超出免费额度即可(超出仅小额收费)。

二、从0到1的实操步骤

1. 让Twilio把图片消息传给你的Python服务

当用户给你的Twilio号码发带图短信时,Twilio会把图片的临时Media URL发到你指定的Webhook地址。你可以写个简单的Flask服务接收:

from flask import Flask, request
import requests
import datetime
import boto3
from twilio.rest import Client
import os

app = Flask(__name__)

# 配置R2客户端(存储用)
s3 = boto3.client(
    "s3",
    endpoint_url="https://<你的Cloudflare账户ID>.r2.cloudflarestorage.com",
    aws_access_key_id=os.getenv("R2_ACCESS_KEY"),
    aws_secret_access_key=os.getenv("R2_SECRET_KEY"),
)

# 配置Twilio客户端(发消息用)
twilio_client = Client(os.getenv("TWILIO_SID"), os.getenv("TWILIO_AUTH_TOKEN"))

@app.route("/sms", methods=["POST"])
def receive_sms():
    # 获取发来的图片URL和发送者号码
    media_urls = request.form.getlist("MediaUrl0")
    sender_num = request.form.get("From")
    
    if media_urls:
        for idx, url in enumerate(media_urls):
            # 下载图片
            img_data = requests.get(url).content
            # 生成唯一文件名,避免重复
            filename = f"img_{sender_num.replace('+', '')}_{datetime.datetime.now().strftime('%Y%m%d%H%M%S')}_{idx}.jpg"
            # 上传到R2存储桶
            s3.put_object(Bucket="<你的R2存储桶名称>", Key=filename, Body=img_data)
            # 把发送者和文件名存到本地txt,方便后续合并
            with open("received_imgs.txt", "a") as f:
                f.write(f"{sender_num},{filename}\n")
    
    return "<Response></Response>"

if __name__ == "__main__":
    app.run(port=5000)
  • 依赖安装:pip install flask requests boto3 twilio
  • 本地服务暴露公网:新手直接用ngrok,下载后打开终端跑ngrok http 5000,复制生成的https URL,到Twilio控制台你的号码的Messaging设置里,把Webhook地址改成这个URL,请求方法选POST。

2. Python合并图片

用Pillow库拼接图片,以纵向合并为例:

from PIL import Image

def merge_images(sender_num):
    # 从txt取出该用户的所有图片文件名
    img_filenames = []
    with open("received_imgs.txt", "r") as f:
        for line in f:
            num, filename = line.strip().split(",")
            if num == sender_num:
                img_filenames.append(filename)
    
    # 从R2下载图片到本地临时文件
    temp_files = []
    for filename in img_filenames:
        resp = s3.get_object(Bucket="<你的R2存储桶名称>", Key=filename)
        temp_path = f"temp_{filename}"
        with open(temp_path, "wb") as f:
            f.write(resp['Body'].read())
        temp_files.append(temp_path)
    
    # 合并图片
    images = [Image.open(fp) for fp in temp_files]
    total_height = sum(img.height for img in images)
    max_width = max(img.width for img in images)
    merged_img = Image.new('RGB', (max_width, total_height))
    
    current_y = 0
    for img in images:
        merged_img.paste(img, (0, current_y))
        current_y += img.height
    
    merged_path = f"merged_{sender_num.replace('+', '')}.jpg"
    merged_img.save(merged_path)
    
    # 清理临时文件
    for fp in temp_files:
        os.remove(fp)
    
    return merged_path

3. 把合并后的图片回传给用户

调用Twilio API发送带图短信:

def send_merged_img(sender_num, merged_path):
    # 上传合并后的图片到Twilio媒体服务
    media = twilio_client.media.create(media_url=f"file://{os.path.abspath(merged_path)}")
    # 发送短信
    twilio_client.messages.create(
        from_="<你的Twilio号码>",
        body="这是你发来的图片合并结果!",
        media_url=[media.url],
        to=sender_num
    )
    # 清理本地合并后的图片
    os.remove(merged_path)

# 示例:给指定用户合并并发送
send_merged_img("+123456789", merge_images("+123456789"))

三、新手避坑指南

  • 所有密钥(R2、Twilio)别直接写代码里,用环境变量读取,避免泄露。
  • ngrok仅用于开发测试,正式上线可以用免费Python托管平台(比如Render免费层)或学生价VPS部署Flask服务。
  • Twilio每月有15美元免费额度,个人测试完全够用,超出后费用也很低,不用担心成本。

内容的提问来源于stack exchange,提问作者RCanaway

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 05:37:24