首页 > 解决方案 > 如何正确使用 Retrofit 从 Android 设备上传文件到 Laravel 服务器

问题描述

我正在尝试使用 Retrofit2 Multipart 编码将图像从 Android Studio 上传到 Laravel 服务器,但我不断收到“500 Internal Server Error”,这意味着服务器端可能出现问题,但我无法确定它是什么.

这是我的接口调用(Android Studio):

@Multipart
@POST("public/imagem")
Call<ResponseBody> uploadImagem(@Part MultipartBody.Part part,
                                @Part("name") RequestBody name,
                                @Part("animal_id") long animal_id,
                                @Part("ativo") int ativo);

这是请求(Android Studio):

    //Create a file object using file path
    File file = new File(filePath);
    // Create a request body with file and image media type
    RequestBody fileReqBody = RequestBody.create(MediaType.parse("image/*"), file);
    // Create MultipartBody.Part using file request-body,file name and part name
    MultipartBody.Part part = MultipartBody.Part.createFormData("upload", file.getName(), fileReqBody);
    //Create request body with text description and text media type
    RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "image-type");

    WebService.getInstance().getService().uploadImagem(part, name, animal_id, 1).enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            if (response.isSuccessful()) {
                //THIS IS WHERE I WANT TO GET
            } else {
                //THIS IS WHERE IM GETTING AT EVERYTIME
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {

        }
    });

这是我的路线(Laravel):

Route::post('imagem','ImagemController@createImagem');

这是“ImagemController”(Laravel)中的“createImagem”函数:

public function createImagem(Request $request){

$destinationPath = url('/midia'); //i have a "midia" folder inside "public" folder
$image = $request->file('part');
$name = $request->input('name');
$image->move($destinationPath, $name);

$dbPath = $destinationPath. '/'.$name;
$imagem = new Imagem();
$imagem->animal_id = $request->input('animal_id');
$imagem->img_url = $dbPath;
$imagem->ativo = $request->input('ativo');   
$imagem->save();

return response()->json($imagem);
}

这些是“Imagem”表中的属性及其类型:

但我收到 500 Internal Server Error,所以服务器端的某些东西可能不符合逻辑上的正确性,你能帮我找出我的代码中有什么问题吗?

附言。我确实对此服务器有其他功能齐全的请求,但它们都只是字段,而这有一个文件,需要多部分编码,与其他请求不同。

编辑:这是服务器错误日志:

[2019-06-11 21:21:03] local.ERROR: Call to a member function move() on null {"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call to a member function move() on null at /.../Controllers/ImagemController.php:28)

所以看来我无法获取文件

$image = $request->file('part');

标签: androidlaravelretrofit2

解决方案


我认为错误可能是因为路径必须是路径而不是 url:

$destinationPath = url('/midia');

如果要将文件移动到公用文件夹,则必须使用public_path()路径:

$image = $request->file('part');
$destinationPath = 'midia';
$name = $request->input('name') .'.'. $image->getClientOriginalExtension();
$image->move(public_path($destinationPath), $name);

如果您想在请求中没有图像时避免错误并且不浪费服务器资源,请在函数开头添加验证:

public function createImagem(Request $request){
    $this->validate($request, [
        'part' => 'required|image|max:2048',
        // other fields validations
    ]);
    // the createImagem logic here
}

如果验证失败,您将不会尝试移动文件并且也不会查询数据库,那么正确的错误响应将自动发送回您可以处理的客户端。


推荐阅读