Python中如何实现一个简单的图片上传存储服务
七牛什么的自定义域名竟然还需要备案,所以花两天时间写了一个简单的图片上传存储服务(基于 flask)
示例,使用 requests上传图片
import requests
def images():
url = ‘http://127.0.0.1:8000/api/images’
files = {‘images’: open(‘desktop.png’, ‘rb’)}
multiple_files = [
(‘images’, (‘11.png’, open(‘11.png’, ‘rb’), ‘image/png’)),
(‘images’, (‘desktop.png’, open(‘desktop.png’, ‘rb’), ‘image/png’))
]
headers = {
‘Api-Key’:
‘InhpeWFuZzA4MDdJBtx4AWlPpI_Oxx1Ki8’,
‘User-Agent’: ‘Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36’
}
# r = requests.post(url, files=multiple_files, headers=headers)
r = requests.post(url, files=files, headers=headers)
print(r.text)
GitHub 地址: https://github.com/honmaple/maple-file
Python中如何实现一个简单的图片上传存储服务
支持自动多尺寸 thumbnail 不?
我来给你一个完整的实现方案。这个服务会包含一个简单的Flask后端,用于接收图片并保存到本地,同时提供一个上传页面。
import os
from flask import Flask, request, render_template, jsonify
from werkzeug.utils import secure_filename
app = Flask(__name__)
# 配置
UPLOAD_FOLDER = 'uploads' # 上传文件保存的目录
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'bmp'} # 允许的文件类型
MAX_CONTENT_LENGTH = 16 * 1024 * 1024 # 最大文件大小:16MB
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = MAX_CONTENT_LENGTH
# 确保上传目录存在
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
def allowed_file(filename):
"""检查文件扩展名是否合法"""
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/')
def index():
"""显示上传页面"""
return render_template('upload.html')
@app.route('/upload', methods=['POST'])
def upload_file():
"""处理文件上传"""
# 检查是否有文件被上传
if 'file' not in request.files:
return jsonify({'error': '没有选择文件'}), 400
file = request.files['file']
# 检查是否选择了文件
if file.filename == '':
return jsonify({'error': '没有选择文件'}), 400
# 检查文件类型
if not allowed_file(file.filename):
return jsonify({'error': '不支持的文件类型'}), 400
# 安全处理文件名
filename = secure_filename(file.filename)
# 生成唯一文件名(避免重名)
import uuid
unique_filename = f"{uuid.uuid4().hex}_{filename}"
# 保存文件
file_path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)
file.save(file_path)
return jsonify({
'success': True,
'filename': unique_filename,
'original_name': filename,
'url': f'/uploads/{unique_filename}'
})
@app.route('/uploads/<filename>')
def uploaded_file(filename):
"""提供已上传文件的访问"""
from flask import send_from_directory
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
if __name__ == '__main__':
app.run(debug=True)
还需要创建一个HTML模板文件 templates/upload.html:
<!DOCTYPE html>
<html>
<head>
<title>图片上传服务</title>
<style>
body { font-family: Arial; max-width: 600px; margin: 50px auto; }
.upload-form { border: 2px dashed #ccc; padding: 30px; text-align: center; }
.file-input { margin: 20px 0; }
.preview { max-width: 300px; margin-top: 20px; display: none; }
.result { margin-top: 20px; padding: 10px; }
</style>
</head>
<body>
<h2>图片上传服务</h2>
<div class="upload-form">
<form id="uploadForm" enctype="multipart/form-data">
<input type="file" id="fileInput" class="file-input" accept="image/*">
<br>
<button type="submit">上传图片</button>
</form>
<img id="preview" class="preview" alt="图片预览">
<div id="result" class="result"></div>
</div>
<script>
document.getElementById('fileInput').addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const preview = document.getElementById('preview');
preview.src = e.target.result;
preview.style.display = 'block';
}
reader.readAsDataURL(file);
}
});
document.getElementById('uploadForm').addEventListener('submit', async function(e) {
e.preventDefault();
const fileInput = document.getElementById('fileInput');
const formData = new FormData();
formData.append('file', fileInput.files[0]);
const resultDiv = document.getElementById('result');
resultDiv.innerHTML = '上传中...';
try {
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
if (data.success) {
resultDiv.innerHTML = `
<strong>上传成功!</strong><br>
文件名: ${data.filename}<br>
<a href="${data.url}" target="_blank">查看图片</a>
`;
} else {
resultDiv.innerHTML = `<strong>错误:</strong> ${data.error}`;
}
} catch (error) {
resultDiv.innerHTML = `<strong>上传失败:</strong> ${error.message}`;
}
});
</script>
</body>
</html>
安装依赖:
pip install flask
运行服务:
python app.py
然后访问 http://localhost:5000 就能看到上传页面了。
这个实现包含了:
- 文件类型和大小验证
- 安全的文件名处理
- 唯一文件名生成(避免冲突)
- 前端预览功能
- 简单的REST API接口
如果需要更复杂的存储(比如数据库记录、云存储),可以在此基础上扩展。
总结:用Flask处理上传,注意安全验证和文件管理。
目前只是保存原图及生成 width=300 的缩略图,后续可能会加上
现在可以使用 url/40965530537.png?width=300&height=100,不过只支持等比缩放
自己架一个图片处理的服务也容易,有开源的一些解决方案可参考,稍作改动可以达到类似于七牛自定义后缀规则的效果 https://github.com/agschwender/pilbox
七牛不是有 api 么 直接上传不就好了~~~
是因为自定义域名要备案才自己写的

