如何正确使用Retrofit将文件从Android设备上传到Laravel服务器

时间:2019-06-11 22:34:10

标签: android laravel retrofit2

我正在尝试使用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,所以服务器端可能不是根据逻辑上正确的东西,您能帮我找出代码中的错误吗?

ps。我确实对该服务器有其他请求,这些请求功能齐全,但是所有请求都只是字段,而该请求有一个文件,与其他文件不同,该文件需要Multipart编码。

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

[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');

2 个答案:

答案 0 :(得分:2)

我认为错误可能是因为path必须是路径而不是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
}

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

答案 1 :(得分:1)

尝试此代码,希望对您有所帮助。

 @Multipart
@POST("public/imagem")
Call<ResponseBody> uploadImagem(@Part MultipartBody.Part part);

如果您使用的是关键部分 $image = $request->file('part');

还要在Java代码中使用键“ part”

Uri uri1 = Uri.parse(event_image);
        File file = new File(uri1.getPath());
        RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);

        MultipartBody.Part image = MultipartBody.Part.createFormData("part", file.getName(), reqFile);



        mService.addEvent(image).enqueue(new Callback<LoginResponse>() {
            @Override
            public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) {

            }

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

            }
        });