【问题标题】:Can't upload canvas image to server using retrofit无法使用改造将画布图像上传到服务器
【发布时间】:2021-09-01 12:50:48
【问题描述】:

我正在尝试发送使用 Canvas 创建的图像。图片没有问题,可以在ImageView中显示。


这是我得到的错误:

D/onFailure: /storage/emulated/0/sign_3.png: open failed: ENOENT (No such file or directory)

即使我获得了写入和读取外部存储的权限,我也收到了错误消息。我从以下日志中发现:

V/ContentValues: Permission is granted

这是我发送图片的代码:

mainactivityBinding.ivSignature.invalidate();
BitmapDrawable drawable = (BitmapDrawable) 
mainactivityBinding.ivSignature.getDrawable();
Bitmap bitmap = drawable.getBitmap();

if(isStoragePermissionGranted()){
      String root = Environment.getExternalStorageDirectory().toString();
        File myDir = new File(root);
        myDir.mkdirs();

        String fname = "sign_"+ Preferences.getKeyIdLogin(getBaseContext()) +".png";
        file = new File (myDir, fname);
        if (file.exists ()) file.delete ();
        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();

        } catch (Exception e) {
            e.printStackTrace();
        };
}

String token = Preferences.getKeyTokenLogin(getBaseContext());
RequestBody postToken = RequestBody.create(okhttp3.MultipartBody.FORM, token);

RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Partbody = MultipartBody.Part.createFormData("upload", file.getName(), reqFile);

Call<ResponseSign> call =getApi().postSign(postToken, body);
        call.enqueue(new Callback<ResponseSign>() {
            @Override
            public void onResponse(Call<ResponseSign> call, Response<ResponseSign> response) {
                String message = response.body().getMessage();
                Log.d("RESPON", "onResponse: " + message);
        }

            @Override
            public void onFailure(Call<ResponseEditProfil> call, Throwable t) {
                String message = response.body().getMessage();
                Log.d("RESPON", "onResponse: " + message);
            }
        });

这是给定存储权限的代码:

public boolean isStoragePermissionGranted() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                checkSelfPermission(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                Log.v(TAG,"Permission is granted");
                return true;
            } else {

                Log.v(TAG,"Permission is revoked");
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
                return false;
            }
        }
        else { //permission is automatically granted on sdk<23 upon installation
            Log.v(TAG,"Permission is granted");
            return true;
        }
    }

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
            //resume tasks needing this permission
        }
    }

这是我的改造界面:

    @Multipart
    @POST("postSign")
    Call<ResponseSign> postSign(@Part("token") RequestBody token, 
                                @Part MultipartBody.Part image);

这是我的清单的内容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.myapps">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
       android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyTheme">

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

我在 android 11 上试用过这个应用程序。
我应该怎么做才能将图像发送到服务器?图像真的必须保存在文件中吗?还是可以直接发送而无需保存到文件?

这是我第一次尝试将图像上传到服务器,如果有一些我不明白的基础知识,请见谅。

谢谢。

【问题讨论】:

  • 您在尝试上传之前没有使用 File.exists()。此外,您在该 catch 块中没有 Toast() 来通知用户。如果有一个问题,你也会继续而不是停止。请调整您的代码。
  • 我已经更改了我的代码并按照您的建议进行了操作。原来错误出在我使用的设备上。我使用的设备没有外部存储器,所以我添加了一个代码来检查设备是否有外部存储器。如果它有外部存储器,它将存储在外部存储器中,如果没有,它将存储在内部存储器中。谢谢你回答我的问题。我真的很感激。

标签: java android android-studio retrofit2 image-upload


【解决方案1】:

我知道我哪里出错了,我应该检查我的设备是否有外部存储器。 如果设备没有外部存储器,文件将存储在内部存储器中。

如果您想知道如何检查内部和外部内存,您可以在此处查看: how to check internal and external storage if exist

【讨论】:

    猜你喜欢
    • 2018-10-05
    • 2014-09-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    • 2019-02-14
    • 2018-07-15
    • 2017-05-21
    • 2017-11-25
    相关资源
    最近更新 更多