在处理iOS Swift客户端上传文件时遇到问题。我在下面完全描述
我的模特:
def avatar_photo_upload(instance, filename):
if filename:
ext = filename.split('.')[-1]
filename = 'avatar.%s' % (ext)
else:
filename = 'avatar.jpg'
return "avatar/%s/%s" %('profile', filename)
class Profile(models.Model):
avatar = models.FileField("Uploaded avatar of profile", storage=OverwriteStorage(), upload_to=avatar_photo_upload, null=True, blank=True)
我的序列化器:
class PhotoUpdateSerializer(ModelSerializer):
file = ImageField(max_length=100000, allow_empty_file=False, use_url=False)
class Meta:
model = Profile
fields = [
'file',
]
我的观点:
class UploadPhotoAPIView(ModelViewSet):
serializer_class = PhotoUpdateSerializer
queryset = Profile.objects.all()
parser_classes = (JSONParser, MultiPartParser, FormParser,)
permission_classes = (IsAuthenticated,)
def upload_avatar(self, request):
serializer = self.get_serializer(data=request.data, context={"request": request})
logger.info('Information incoming!')
if serializer.is_valid():
profile = Profile.objects.get(user=request.user)
profile.avatar = request.FILES.get('file')
profile.save()
return Response({ 'status': 'ok', 'avatar': get_avatar_url(request, '300x300', 'user', profile.user_id) }, status=status.HTTP_201_CREATED)
else:
logger.error('Toan Error' + str(serializer.errors))
return Response(serializer.errors, status=status.HTTP_501_NOT_IMPLEMENTED)
最后,这是我的网址:
url(r'^account/upload_avatar/$', UploadPhotoAPIView.as_view({'post': 'upload_avatar'}))
我相信我会一直做下去,直到在iOS Swift中测试API,它都会返回错误:
客户请求
func uploadImage(image:UIImage) {
let imageData:NSData = UIImageJPEGRepresentation(image, 100)
SRWebClient.POST("https://api.com/api/v1/users/account/upload_avatar/")
.data(imageData, fieldName:"file", data: ["filename":"avatar","ext":".jpg"])
.send({(response:AnyObject!, status:Int) -> Void in
// process success response
},failure:{(error:NSError!) -> Void in
// process failure response
})
}
错误回溯:
[请求]:POST https://api.com/api/v1/users/account/upload_avatar/ [回应]:{URL: https://api.com/api/v1/users/account/upload_avatar/} { 状态码:501,标题{ “内容长度” =( 84 ); “内容类型” =( “应用程序/ json” ); 日期=( “ 2018年10月10日星期三10:41:31 GMT” ); 服务器=( 云耀斑 ); 变化=( 起源 ); 允许=( “发布,选项” ); “ cf-ray” =( “ 46787998dfaa8502-HKG” ); “ expect-ct” =( “ max-age = 604800,report-uri = \” https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct \“” ); “ x-frame-options” =( SAMEORIGIN ); }} [数据]:84个字节[结果]:成功:{ 文件=( “提交的数据不是文件。请检查表单上的编码类型。” ); } [时间轴]:时间轴:{“请求开始时间”:560860890.985,“初始响应时间”:560860891.099,“请求完成时间”: 560860891.100,“序列化完成时间”:560860891.100,“延迟”:0.114秒,“请求持续时间”:0.115秒,“序列化 持续时间”:0.000秒,“总持续时间”:0.115秒}▿请求: 可选的 ▿一些:https://api.com/api/v1/users/account/upload_avatar/ ▿网址:可选 ▿一些:https://api.com/api/v1/users/account/upload_avatar/ -_url:https://api.com/api/v1/users/account/upload_avatar/ -cachePolicy:0 -timeoutInterval:60.0 -mainDocumentURL:无 -networkServiceType:__C.NSURLRequestNetworkServiceType -allowCellularAccess:true Method httpMethod:可选 -一些:“ POST” ▿allHTTPHeaderFields:可选> ▿一些:2要素 ▿0:2个元素 -键:“内容类型” -值:“应用程序/ x-www-form-urlencoded; charset = utf-8” ▿1:2元素 -键:“授权” - 值: “智威汤逊eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyMSwidXNlcm5hbWUiOiJkdW9uZ251aGFiYW5nIiwiZXhwIjoyNDAzMTY4MDU5LCJlbWFpbCI6ImRyYWZ0bGlnb25ncXVhbjdAZ21haWwuY29tIn0.ZfDBOaAhKsRSpZl3mP87doR34UtlGISfeqJYlJnxcVI” B httpBody:可选 ▿一些:105字节 -数量:105 ▿指针:0x00006000025d2510 -指针值:105553155925264 -httpBodyStream:无 -httpShouldHandleCookies:是 -httpShouldUsePipelining:false响应:可选 -一些:{网址:https://api.com/api/v1/users/account/upload_avatar/} { 状态码:501,标题{ “内容长度” =( 84 ); “内容类型” =( “应用程序/ json” ); 日期=( “ 2018年10月10日星期三10:41:31 GMT” ); 服务器=( 云耀斑 ); 变化=( 起源 ); 允许=( “发布,选项” ); “ cf-ray” =( “ 46787998dfaa8502-HKG” ); “ expect-ct” =( “ max-age = 604800,report-uri = \” https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct \“” ); “ x-frame-options” =( SAMEORIGIN );数据:可选 ▿一些:84字节 -数量:84 ▿指针:0x00006000025d0c00 -指针值:105553155918848▿结果:成功:{ 文件=( “提交的数据不是文件。请检查表单上的编码类型。” ); } ▿成功:1个要素 ▿0:2个元素 -键:文件 ▿值:1个元素 -0:提交的数据不是文件。检查表单上的编码类型。 ▿时间轴:时间轴:{“请求开始时间”: 560860890.985,“初始响应时间”:560860891.099,“请求完成时间”:560860891.100,“序列化完成时间”: 560860891.100,“等待时间”:0.114秒,“请求持续时间”:0.115秒,“序列化持续时间”:0.000秒,“总持续时间”:0.115秒} -requestStartTime:560860890.984645 -initialResponseTime:560860891.099072 -requestCompletedTime:560860891.099792 -serializationCompletedTime:560860891.099964 -延迟时间:0.11442697048187256 -requestDuration:0.11514699459075928 -序列化持续时间:0.00017201900482177734 -totalDuration:0.11531901359558105 _ _metrics:可选 -一些:(任务间隔)<_NSConcreteDateInterval:0x600000b68980>(开始日期)2018-10-10 10:41:30 +0000 +(持续时间)0.115085秒= (结束日期)2018-10-10 10:41:31 +0000(重定向计数)0(交易 指标)(请求){URL: https://api.com/api/v1/users/account/upload_avatar/} (响应){URL: https://api.com/api/v1/users/account/upload_avatar/} { 状态码:501,标题{ “内容长度” =( 84 ); “内容类型” =( “应用程序/ json” ); 日期=( “ 2018年10月10日星期三10:41:31 GMT” ); 服务器=( 云耀斑 ); 变化=( 起源 ); 允许=( “发布,选项” ); “ cf-ray” =( “ 46787998dfaa8502-HKG” ); “ expect-ct” =( “ max-age = 604800,report-uri = \” https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct \“” ); “ x-frame-options” =( SAMEORIGIN ); }}(获取开始)2018-10-10 10:41:30 +0000(域查找开始)(null)(域查找结束)(null)(连接开始)(null) (安全连接开始)(空)(安全连接结束)(空) (连接结束)(空)(请求开始)2018-10-10 10:41:30 +0000 (请求结束)2018-10-10 10:41:30 +0000(响应开始)2018-10-10 10:41:31 +0000(响应结束)2018-10-10 10:41:31 +0000(协议 名称)h2(代理连接)否(重用连接)是(获取类型) 网络负载
问题是什么,它来自服务器还是客户端?请给我一个建议。预先感谢!
答案 0 :(得分:1)
您必须将内容类型作为多部分表单数据进行传递。
class UploadPhotoAPIView(ModelViewSet):
serializer_class = PhotoUpdateSerializer
queryset = Profile.objects.all()
parser_classes = (JSONParser, MultiPartParser, FormParser,)
permission_classes = (IsAuthenticated,)
def upload_avatar(self, request):
serializer = self.get_serializer(instance=Profile.objects.get(user=request.user), data=request.data, context={"request": request})
logger.info('Information incoming!')
if serializer.is_valid():
serializer.save()
return Response({ 'status': 'ok', 'avatar': get_avatar_url(request, '300x300', 'user', profile.user_id) }, status=status.HTTP_201_CREATED)
else:
logger.error('Toan Error' + str(serializer.errors))
return Response(serializer.errors, status=status.HTTP_501_NOT_IMPLEMENTED)
在客户端以多部分形式发送数据