You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:29:44