简体   繁体   English

使用翻新2上传文件时出错

[英]Error uploading file with Retrofit 2

The system I am working has an end point that receives a file picture in order to set user's profile picture. 我正在工作的系统有一个接收文件图片的端点,以便设置用户的个人资料图片。 If I try sending it via Postman, everything works fine: 如果我尝试通过邮递员发送,一切正常:

在此处输入图片说明

When I try to upload it from my App using retrofit it always fail. 当我尝试使用改造从我的应用程序上载它时,它总是失败。 Code + stacktrace is below: 代码和堆栈跟踪如下:

Server side code: 服务器端代码:

begin
         user = User.find(doorkeeper_token.resource_owner_id)
         image = params[:image]
         attachment = {
             :filename => image[:filename],
             :type => image[:type],
             :headers => image[:head],
             :tempfile => image[:tempfile]
         }

         image_link = ""
         if params[:upload_type] == "profile"
           user.profile_image = ActionDispatch::Http::UploadedFile.new(attachment)
           image_link = get_image_path(user.id,params[:upload_type],"original",attachment[:filename])
           user.image_profile_original = get_image_path(user.id,params[:upload_type],"original",attachment[:filename])
           user.image_profile_large = get_image_path(user.id,params[:upload_type],"large",attachment[:filename])

 /*e22*/
    @Multipart
    @POST("user/upload_image")
    fun uploadUserImage(@Header("Authorization") authHeader: String,  @Part("upload_type") description: RequestBody, @Part file: MultipartBody.Part): Call<ResponseWrapper>

 fun uploadUserImage(image: Uri) {
        val source = File(image.path)
        val requestFile = RequestBody.create(MediaType.parse(getContext().contentResolver.getType(image)), source)
        val body = MultipartBody.Part.createFormData("image", "profile", requestFile)
        val description = RequestBody.create(okhttp3.MultipartBody.FORM, "profile")
        mMessenger.uploadUserImage(getAuthorizationHeader(), description, body).enqueue(ResponseWrapperCallback(EventCatalog.e0022))
    }

Request response: 要求回复:

E/ResponseWrapperCallback: Failed processing request: profile: open failed: ENOENT (No such file or directory)
E/ResponseWrapperCallback: HTTP request mapped to event e0022 finished with error

Edit 1 编辑1

I do think that this error has something to do with how the File object is being instantiated. 我确实认为此错误与File对象的实例化有关。 If I create the file straight from the Uri, its real path seems not to be sent to server. 如果我直接从Uri创建文件,则它的真实路径似乎不会发送到服务器。 I say that because of the error log above, it says that it doesn't located the file on the retrieved device's Uri. 我说这是因为上面的错误日志,它说它没有在检索到的设备的Uri上找到该文件。 I've tried to extract file's real path from the Uri, however, error log from server has changed to: 我试图从Uri中提取文件的真实路径,但是,服务器的错误日志已更改为:

/storage/emulated/0/Marvel/Media/Characters/Adam Warlock.jpeg: open failed: EACCES (Permission denied)

The way I'm instantiating the File object with the real file path is like that: 我使用真实文件路径实例化File对象的方式是这样的:

   private fun getRealPathFromURI(contentURI: Uri): String {
        val result: String
        val cursor = getContext().contentResolver.query(contentURI, null, null, null, null)
        if (cursor == null) {
            result = contentURI.path
        } else {
            cursor.moveToFirst()
            val idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
            result = cursor.getString(idx)
            cursor.close()
        }
        return result
    }

//....

val source = File(getRealPathFromURI(Uri))

Edit 2 编辑2

As per user Anurag Singh request, below is the Manifest and OS information: 根据用户Anurag Singh的请求,以下是清单和操作系统信息:

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

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.1"

    defaultConfig {
        applicationId "***"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        multiDexEnabled true
        vectorDrawables.useSupportLibrary = true
    }
}

Edit 3 编辑3

This is the code generated by Postman which works fine! 这是Postman生成的代码,效果很好!

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");

RequestBody body = RequestBody.create(mediaType, "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"image\"; filename=\"sample 2.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"upload_type\"\r\n\r\nprofile\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--");

Request request = new Request.Builder()
  .url("http://********/user/upload_image")
  .post(body)
  .addHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
  .addHeader("authorization", "Bearer ******")
  .addHeader("cache-control", "no-cache")
  .addHeader("postman-token", "******")
  .build();

Response response = client.newCall(request).execute();

Try adding below permission in AndroidManifest.xml 尝试在AndroidManifest.xml添加以下权限

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

Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. 从Android 6.0(API级别23)开始,用户在应用程序运行时(而不是在安装应用程序时)授予应用程序权限。 Requesting Permissions at Run Time 在运行时请求权限

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM