配置SFTP服务器
groupadd sftp
useradd -g sftp -s /sbin/nologin django
mkdir -p /data/sftp/django
usermod -d /data/sftp/django django
chown root:sftp /data/sftp/django
chmod 755 /data/sftp/django
# 上传文件的文件夹位置
chown django:sftp /data/sftp/django/medias
chmod 755 /data/sftp/django/medias # 这个一定要是 755 777 不行
问题描述:packet_write_wait: Connection to 127.0.0.1 port 22: Broken pipe Couldn't read packet: Connection reset by peer
解决方法: chmod 755 /data/sftp/django
这个问题的原因是ChrootDirectory的权限问题,你设定的目录必须是root用户所有,否则就会出现问题。所以请确保sftp用户根目录的所有人是root, 权限是 750 或者 755。注意以下两点原则:
- 目录开始一直往上到系统根目录为止的目录拥有者都只能是 root,用户组可以不是 root
- 目录开始一直往上到系统根目录为止都不可以具有群组写入权限
Django使用SFTP存储
安装django-storages
pip install django-storages
问题描述:No module named 'paramiko'
解决方法:pip install paramiko
在Django服务器判断SFTP中文件是否存在
在{your_proj}/test.py
添加:
#SFTP test
from storages.backends.sftpstorage import SFTPStorage
SFS = SFTPStorage()
obj = SFS.listdir('/medias')
print(obj)
if SFS.exists("/medias/images/xxxx.png"):
print("Yes")
else:
print("No")
使用python3 manage.py test
运行
在Django中配置SFTP存储
在{yourapp}/model.py
中添加一下内容:
from storages.backends.sftpstorage import SFTPStorage
SFS = SFTPStorage()
class Class(models.Model):
index_image = StdImageField(storage=SFS, upload_to='images', blank=True, null=True,
variations={'thumbnail': (100, 75)},
verbose_name='截图')
# 主要是这个 storage=SFS
def index_image_preview(self):
if self.index_image:
print(self.index_image.thumbnail.url)
return format_html('<a href="{path}" target="_blank"><img src="{thumbnail}" width="100px"/></a>',
path=self.index_image.url,
thumbnail=self.index_image.thumbnail.url)
index_image_preview.short_description = "首页截图"
index_image_preview.allow_tags = True
class Meta:
abstract = True # 抽象类
新建中间件 {your_app}/middleware.py
:
import mimetypes
from storages.backends.sftpstorage import SFTPStorage
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
class SFTPMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
SFS = SFTPStorage()
response = self.get_response(request)
path = request.get_full_path()
# 这是我的业务代码,可以根据自己需要修改
if 'image' in path and SFS.exists(path):
file = SFS._read(path)
# type, encoding = mimetypes.guess_type(path)
response = HttpResponse(file, content_type="image/png") #content_type=type)
# response['Content-Disposition'] = u'attachment; filename="{filename}"'.format(filename=path)
return response
{your_proj}/settings.py
添加SFTP配置和自己的中间件
DEFAULT_FILE_STORAGE = 'storages.backends.sftpstorage.SFTPStorage'
SFTP_STORAGE_HOST = '192.168.0.222' # sftp ip
SFTP_STORAGE_ROOT = '/medias/'
SFTP_STORAGE_PARAMS = {
'username': 'django',
'password': 'django',
'allow_agent': False,
'look_for_keys': False,
}
MIDDLEWARE = [
...,
'your_app.middleware.SFTPMiddleware', # 自建 SFTP 中间件
]