When you are working with AWS serverless, You probably has faced body size limit for your lambda function. Basically It won't allow file uploads beyond size limit specified.
Here is guide if you are using Django in your website and deployed on AWS Lambda + API Gateway ( Zappa ) And want to allow file uploads of any size in Django Admin using AWS S3 Identity based uploads.
Write One API which give response as following json :
`/api/awsIdentity/` // any endpoint you like make sure authenticated and GET only
{ "IdentityId": "",
"Token": "",
"bucket_name": "",
"bucket_region": "",
"auth_role_arn": ""
}
Your widget for File Field And Admin Form will looks like this : from django import forms
from django.contrib import admin
class AWSIdentityS3FileWidget(forms.Textarea):
template_name = 's3_identity_file_field.html'
# GET and for logged in users only
identity_api_url = "/api/awsIdentity/"
def __init__(self, *args, **kwargs):
super(AWSIdentityS3FileWidget, self).__init__(*args, **kwargs)
self.attrs['identity_api_url'] = self.identity_api_url
self.attrs['rows'] = 2
class YourModelForm(forms.ModelForm):
class Meta:
model = YourModel
exclude = ()
your_file = forms.CharField(
label='Your File', required=False,
widget=AWSIdentityS3FileWidget())
def save(self, commit=True):
if self.cleaned_data.get("your_file"):
# This will set your file to public access
# using boto3
set_my_file_as_public(self.cleaned_data.get("your_file"))
return super(YourModelForm, self).save(commit=commit)
class YourModelAdmin(admin.ModelAdmin):
form = YourModelForm
Your Widget HTML will be : `s3_identity_file_field.html`
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.82.0.min.js"></script>
<input type="file" id="file-chooser" class="toggle_hide_display" />
<textarea class="toggle_hide_display" readonly="true" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
{% if widget.value %}{{ widget.value }}{% endif %}</textarea>
<span id="loading_widget"></span>
{% if widget.value %} <span class="toggle_hide_display">Remove File : </span> <input type="checkbox" id="empty_text_area" class="toggle_hide_display" />{% endif %}
<script>
if (!$) {
$ = django.jQuery;
}
$("#loading_widget").text('Loading ...').show();
$('.toggle_hide_display').hide();
$.getJSON("{{widget.attrs.identity_api_url}}", function( data ) {
var bucketName = data.bucket_name;
var bucketRegion = data.bucket_region;
var IdentityId = data.IdentityId;
var webtoken = data.Token;
var role_arn = data.auth_role_arn;
var bucket = null;
var params = {
RoleArn: role_arn,
WebIdentityToken: webtoken
};
AWS.config.region = bucketRegion;
AWS.config.credentials = new AWS.WebIdentityCredentials(params, function(err) {
console.log(err, err.stack);
});
AWS.config.credentials.get(function(err) {
if (err) alert(err);
bucket = new AWS.S3({
params: {
Bucket: bucketName
},
httpOptions: {
timeout: 600000
}
});
$("#loading_widget").hide();
$('.toggle_hide_display').show();
});
$('#empty_text_area').on('change', function(ele){
if($('input[id="empty_text_area"]:checked').length > 0){
$('#{{widget.attrs.id}}').val('');
}
});
var fileChooser = document.getElementById('file-chooser');
fileChooser.addEventListener('change', function() {
$("#loading_widget").text('Uploading ...').show();
var file = fileChooser.files[0];
if (file) {
var objKey = 'public/' + IdentityId + '/' + file.name;
var params = {
Key: objKey,
ContentType: file.type,
Body: file
};
bucket.putObject(params, function(err, data) {
if (err) {
console.log('error upload', data);
} else {
$('#{{widget.attrs.id}}').val(objKey);
}
$("#loading_widget").hide();
});
} else {
console.log('error choose file');
}
}, false);
});
</script>
Hope Its working for you. leave comment if not.
Comments
There are currently no comments
New Comment