Android基于Retrofit上传图片至Django时request.FILES为空求助
解决Retrofit上传图片到Django时
request.FILES为空的问题 看起来你的文件上传请求没有正确携带文件数据,导致Django端接收不到上传的文件。我帮你梳理几个关键问题和对应的修复方案:
1. 修正文件RequestBody的MediaType
你当前用MediaType.parse("multipart/form-data")作为文件的类型,这是错误的——multipart/form-data是整个请求的Content-Type,Retrofit会自动处理这个字段,文件对应的MediaType应该是图片的实际MIME类型(比如image/jpeg、image/png)。
修改Android端的filePart创建代码:
// 通过Uri获取文件的MIME类型 String mimeType = getContentResolver().getType(filePath); // 用正确的MIME类型创建RequestBody RequestBody filePart = RequestBody.create(MediaType.parse(mimeType), originalFile);
如果getContentResolver().getType()无法获取到类型,也可以根据图片格式手动指定,比如JPG图片用MediaType.parse("image/jpeg")。
2. 修正MultipartBody.Part的文件名参数
你创建MultipartBody.Part时用了完整文件路径作为文件名,这可能导致解析异常。应该传入文件的实际名称:
// 用originalFile.getName()代替path作为文件名 MultipartBody.Part file = MultipartBody.Part.createFormData("upload", originalFile.getName(), filePart);
3. 确保getRealPathFromURI方法能正确获取文件路径
如果你的getRealPathFromURI方法没有正确拿到文件的真实路径,会导致originalFile指向一个不存在的文件,自然无法完成上传。这里给你一个兼容Android不同版本的实现:
private String getRealPathFromURI(Uri uri) { String path = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (DocumentsContract.isDocumentUri(this, uri)) { String docId = DocumentsContract.getDocumentId(uri); // 处理媒体文件Uri if ("com.android.providers.media.documents".equals(uri.getAuthority())) { String id = docId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=" + id; path = getPathFromMediaStore(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection); } // 处理下载文件Uri else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); path = getPathFromMediaStore(contentUri, null); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { // 处理普通content类型Uri path = getPathFromMediaStore(uri, null); } else if ("file".equalsIgnoreCase(uri.getScheme())) { // 处理file类型Uri path = uri.getPath(); } } else { // 低版本直接从MediaStore获取路径 path = getPathFromMediaStore(uri, null); } return path; } private String getPathFromMediaStore(Uri uri, String selection) { String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(uri, projection, selection, null, null); if (cursor != null) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String path = cursor.getString(columnIndex); cursor.close(); return path; } return null; }
4. 验证Retrofit接口定义
你的接口定义本身没问题,但可以简化一下(@Part的键名已经在createFormData里指定,无需重复写):
@Multipart @POST("/uploadImage/") Call<ResponseBody> uploadFile(@Part MultipartBody.Part file);
最后测试修改后的代码
修改完成后重新上传,Django端应该就能在request.FILES里拿到"upload"对应的文件了。你可以在Django视图里添加保存逻辑验证:
def uploadImage(request): if request.method == "POST": print(request.FILES) if 'upload' in request.FILES: print("success!") upload = request.FILES['upload'] # 将文件保存到服务器指定目录 with open(f"/your/save/path/{upload.name}", 'wb+') as destination: for chunk in upload.chunks(): destination.write(chunk) return HttpResponse("File uploaded successfully") else: print("something's wrong") return HttpResponse("No file received")
内容的提问来源于stack exchange,提问作者Jana Magdeska
相关产品推荐
相关产品推荐

