我正在尝试直接在Django中设置更大的音频文件到s3上传。 我基本上遵循这里https://devcenter.heroku.com/articles/s3-upload-python的Heroku的Direct To S3教程,它更适合Flask。我也找不到Django调试程序引用的get请求。预先感谢您的帮助。
我收到以下错误:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/sign-s3/?file_name=piano.wav&file_type=audio/wav
Django Version: 2.0
Python Version: 3.6.5
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sitemaps',
'django.contrib.sites',
'crispy_forms',
'tinymce',
'storages',
'ckeditor',
'ckeditor_uploader',
'main',
'contact',
'accounts',
'events',
'news',
'project_settings',
'django_countries',
'publications',
'event_tracker',
'event_signup']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/Users/Tommy/anaconda3/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
35. response = get_response(request)
File "/Users/Tommy/anaconda3/lib/python3.6/site-packages/django/utils/deprecation.py" in __call__
97. response = self.process_response(request, response)
File "/Users/Tommy/anaconda3/lib/python3.6/site-packages/django/middleware/clickjacking.py" in process_response
26. if response.get('X-Frame-Options') is not None:
Exception Type: AttributeError at /sign-s3/
Exception Value: 'str' object has no attribute 'get'
Views.py文件:
def committee_new_podcast(request, id):
template = "main/add_podcast.html"
committee = get_object_or_404(Committee, comm_id=id)
if request.user.is_authenticated:
if Member.objects.filter(user=request.user).exists():
member = Member.objects.get(user=request.user)
if CommitteeMember.objects.filter(Q(is_chair=True) | Q(is_deputy=True)).filter(abila=member, comm=committee.comm_id) or request.user.is_staff:
if request.method == 'POST':
form = CommitteePodcastForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.comm_id = committee
instance.member = member
instance.sound = request.form['avatar-url']
instance.save()
messages.success(request, 'Committee Podcast Was Created',
"alert alert-success alert-dismissible")
else:
form = CommitteePodcastForm()
else:
form = ''
messages.success(request, 'You must be a chair or deputy to access this page.',
"alert alert-danger alert-dismissible")
elif request.user.is_staff:
if request.method == 'POST':
form = CommitteePodcastForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.comm_id = committee
instance.save()
messages.success(request, 'Committee Podcast Was Created',
"alert alert-success alert-dismissible")
else:
form = CommitteePodcastForm()
else:
form = ''
pass
else:
form = ''
messages.success(request, 'You must be logged in to access this page.',
"alert alert-danger alert-dismissible")
context = {
'committee': committee,
'form': form,
}
return render(request, template, context)
def sign_s3(request):
S3_BUCKET = settings.AWS_STORAGE_BUCKET_NAME
file_name = request.GET.get('file_name')
file_type = request.GET.get('file_type')
s3 = boto3.client('s3')
presigned_post = s3.generate_presigned_post(
Bucket = S3_BUCKET,
Key = file_name,
Fields = {"acl": "public-read", "Content-Type": file_type},
Conditions = [
{'acl': "public-read"},
{"Content-Type": file_type}
],
ExpiresIn = 3600
)
return json.dumps({
'data': presigned_post,
'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name),
})
Javascript:
<script>
(function() {
document.getElementById('file_input').onchange = function(){
var files = document.getElementById('file_input').files;
var file = files[0];
if(!file){
return alert("No file selected.");
}
getSignedRequest(file);
}
})();
function getSignedRequest(file){
var xhr = new XMLHttpRequest();
xhr.open("GET", "/sign-s3?file_name="+file.name+"&file_type="+file.type);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200){
var response = JSON.parse(xhr.responseText);
uploadFile(file, response.data, response.url);
}
else{
alert("Could not get signed URL.");
}
}
}
xhr.send();
}
function uploadFile(file, s3Data, url){
var xhr = new XMLHttpRequest();
xhr.open("POST", s3Data.url);
var postData = new FormData();
for(key in s3Data.fields){
postData.append(key, s3Data.fields[key]);
}
postData.append('file', file);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4){
if(xhr.status === 200 || xhr.status == 204){
document.getElementById("sound-url").value = url;
}
else {
alert("Could not upload file.");
}
}
}
xhr.send(postData)
}
</script>
答案 0 :(得分:2)
我知道我应该一直使用HttpResponse返回JSON数据。
def sign_s3(request):
S3_BUCKET = settings.AWS_STORAGE_BUCKET_NAME
file_name = request.GET.get('file_name')
file_type = request.GET.get('file_type')
s3 = boto3.client('s3')
presigned_post = s3.generate_presigned_post(
Bucket = S3_BUCKET,
Key = file_name,
Fields = {"acl": "public-read", "Content-Type": file_type},
Conditions = [
{'acl': "public-read"},
{"Content-Type": file_type}
],
ExpiresIn = 3600
)
data = json.dumps({
'data': presigned_post,
'url': 'https://%s.s3.amazonaws.com/%s' % (S3_BUCKET, file_name),
})
return HttpResponse(data, content_type='json')