我正在尝试使用保管箱作为媒体保护。我正在尝试通过django-storages实现。
settings.py
DEFAULT_FILE_STORAGE = 'storages.backends.dropbox.DropBoxStorage'
DROPBOX_OAUTH2_TOKEN = 'token'
DROPBOX_ROOT_PATH = '/media/'
models.py
logo = models.ImageField(upload_to=r'logo/%Y/%m/')
image = models.ImageField(upload_to=r'photos/%Y/%m/',
help_text='Image size: Width=1080 pixel. Height=1920 pixel',)
错误
请求方法:|开机自检
请求网址:| http://127.0.0.1:8000/add
Django版本:| | 2.1.8
异常类型:| ValidationError
异常值:| 'D:/media/10506738_10150004552801856_220367501106153455_o.jpg'与模式'(/(。| [\ r \ n])| id:。)|(rev:[0-9a-f] {9,})|( ns:[0-9] +(/.*)?)'
控制台
dropbox.stone_validators.ValidationError:'D:/media/10506738_10150004552801856_220367501106153455_o.jpg'与模式'(/(.|[\r\n])|id:.)|(rev:[0-9a- f] {9,})|(ns:[0-9] +(/.*)?)'
我不知道为什么会发生此错误?
答案 0 :(得分:1)
此错误消息来自Dropbox API,表明为Dropbox API调用提供的“路径”没有预期的格式。例如,如果您要上传文件,则提供的“路径”将是Dropbox帐户中要放置上传数据的路径。
您正在提供值:
D:/media/10506738_10150004552801856_220367501106153455_o.jpg
(这似乎是本地Windows文件系统路径。)
您提供的Dropbox路径应类似于:
/media/10506738_10150004552801856_220367501106153455_o.jpg
(这是相对于Dropbox根的路径。它没有驱动器号。)
您需要深入研究代码,以查看为什么/为什么将错误类型的路径提供给Dropbox。
答案 1 :(得分:1)
对于为什么发生此错误,其他答案不太正确。投递箱存储对象后端使用django实用程序(django.utils._os.safe_join)
来验证目标操作系统的文件名。参见代码here
即使您传递了upload_to
参数,该参数给出了Unix风格的路径(类似/ save / path),django实用程序也会确保该保存路径的根与操作系统的基本路径匹配:( 。dropbox SDK不喜欢前缀为所需保存路径的驱动器(AKA C:/path/file.name不是Dropbox的有效保存目录)。
要在Windows上执行此操作,请确保您做几件事
首先,像这样修改存储后端_full_path方法(或创建自己的子类)。
def _full_path(self, name):
if name == '/':
name = ''
print('Root path in dropbox.storage : ', self.root_path)
# If the machine is windows do not append the drive letter to file path
if os.name == 'nt':
final_path = os.path.join(self.root_path, name).replace('\\', '/')
# Separator on linux system
sep = '//'
base_path = self.root_path
if (not os.path.normcase(final_path).startswith(os.path.normcase(base_path + sep)) and
os.path.normcase(final_path) != os.path.normcase(base_path) and
os.path.dirname(os.path.normcase(base_path)) != os.path.normcase(base_path)):
raise SuspiciousFileOperation(
'The joined path ({}) is located outside of the base path '
'component ({})'.format(final_path, base_path))
# TODO Testing
print('Full file path in storage.dropbox._full_path : ', final_path)
return final_path
else:
return safe_join(self.root_path, name).replace('\\', '/')
第二,确保将内容和名称传递给模型FileField。我没有明确传递文件内容和名称时遇到麻烦(关于上传的文件上下文是否保留文件名?)。我重新实现了这样的模型保存方法
def save(self, *args, **kwargs):
# Save file
## Save raw entry from user ##
# Extract files contents
try:
uploaded_raw_entry = kwargs['upload_raw_entry']
except KeyError:
raise UploadError(('No file was passed from the admin interface. ' +
'Make sure a ContentFile was passed when calling this models save method'))
# Test raw_directory_path TODO Remove after testing
print('Raw entry name from model.save : ', raw_directory_path(self, uploaded_raw_entry.name))
with uploaded_raw_entry.open(mode='rb') as f:
raw_entry_content = f.read()
raw_entry_file = ContentFile(content=raw_entry_content.encode('utf-8'),
name=raw_directory_path(self, uploaded_raw_entry.name))
# Save the content file into a model field
raw_entry_file.open(mode='rb')
self.raw_entry.save(raw_entry_file.name, raw_entry_file, save=False)
raw_entry_file.close()
这绝对可以在Windows上使用,但是需要额外的步骤:)
答案 2 :(得分:0)
问题出在Windows操作系统路径上。我尝试在Ubuntu中使用相同的设置。它在那里完美地工作。
答案 3 :(得分:0)
我也在Linux工作站上也遇到了这个问题-因此,@ greg的答案的等效Linux答案是在您的备份名称中添加"/"
:
import sys, os
import dropbox
from dropbox.files import WriteMode
from dropbox.exceptions import ApiError, AuthError
# Add OAuth2 access token here.
TOKEN = '<your-token>'
data_path = './data_files'
filename = 'my-file-backup.txt'
BACKUPPATH = "/"+filename # <----- This should do the trick!
# Uploads contents of filename to Dropbox
def backup():
current_file_path = os.path.join(data_path, filename)
with open(current_file_path, 'rb') as f:
print("Uploading " + filename + " to Dropbox as " + BACKUPPATH + "...")
try:
dbx.files_upload(f.read(), BACKUPPATH, mode=WriteMode('overwrite'))
except ApiError as err:
if (err.error.is_path() and
err.error.get_path().reason.is_insufficient_space()):
sys.exit("ERROR: Cannot back up; insufficient space.")
elif err.user_message_text:
print(err.user_message_text)
sys.exit()
else:
print(err)
sys.exit()
因此,错误消息非常混乱-问题的文件名和路径不是您的本地文件,而是Dropbox远程文件名和路径。