teratail header banner
teratail header banner
質問するログイン新規登録

質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

1144閲覧

Android Studio OkHttp3 でサーバーにファイルをアップロード

ak.n

総合スコア305

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2023/11/08 13:22

編集2023/11/08 14:55

0

0

OkHttp3 を用いて、Android 端末の「ピクチャ」フォルダから、画像ファイルを選択し、サーバーにアップロードすることを考えています。

ファイル選択ダイアログを開き、ユーザーがファイルを選択し、決定した際に実行される関数の中身を抜粋しています。(実際には実行時パーミッション等の処理がありもう少し複雑です)

kotlin

1val file = File(crop_uri.toString()) 2val filename = file.name 3val boundary = System.currentTimeMillis().toString() 4 5val contentResolver = this.contentResolver 6val mimeType = contentResolver.getType(crop_uri) 7val mediaType = mimeType?.toMediaTypeOrNull() 8 9if (mediaType != null) { 10 11 val requestBody: RequestBody = MultipartBody.Builder(boundary).setType(MultipartBody.FORM) 12 .addFormDataPart("file", filename, file.asRequestBody(mediaType)) 13 .build() 14 15 val url = resources.getString(R.string.url_upload_file) 16 17 val request = Request.Builder() 18 .url(url) 19 .post(requestBody) 20 .build() 21 22 client.newCall(request).enqueue(object : Callback { 23 24 override fun onFailure(call: Call, e: IOException) { 25 println("ネットワークエラー: ${e.message}") 26 } 27 28 override fun onResponse(call: Call, response: Response) { 29 if (response.isSuccessful) { 30 println("ファイルがアップロードされました") 31 } else { 32 println("アップロード中にエラーが発生しました: ${response.code}") 33 } 34 response.close() 35 } 36 }) 37}

デバッガでは、

file = {File@28789} "content:/com.android.providers.media.documents/document/image%3A1000000034" filename = "image%3A1000000034" boundary = "1699448759165" contentResolver = {ContextImpl$ApplicationContentResolver@28792} mimeType = "image/jpeg" mediaType = {MediaType@28794} image/jpeg

となっています。

エラーですが、onFailure に行ってしまいます。

2023-11-08 21:56:10.302 14056-14056 System.out com.*****.***** I ここまでOK 2023-11-08 21:56:10.331 14056-14215 okhttp.OkHttpClient com.*****.***** I --> POST https://hogehoge.com/upload_file.php 2023-11-08 21:56:10.331 14056-14215 okhttp.OkHttpClient com.*****.***** I Content-Type: multipart/form-data; boundary=1699448170298 2023-11-08 21:56:10.332 14056-14215 okhttp.OkHttpClient com.*****.***** I Content-Length: 161 2023-11-08 21:56:10.333 14056-14215 System.out com.*****.***** I ネットワークエラー: content:/com.android.providers.media.documents/document/image%3A1000000034: open failed: ENOENT (No such file or directory)

となります。
ファイルを開くことに失敗しているようですが、理由がわかりません。
実行時パーミッションにより、android.Manifest.permission.READ_MEDIA_IMAGES は granted です。
url は投稿上 hogehoge にしていますが、実際の動作では、存在する URL です。

開発環境は、以下のとおりです。
同じ課題で躓かれた方がいらっしゃいましたら、よろしくお願いします。

Android Studio Giraffe | 2022.3.1 Patch 2
targetSdk 34
Android Gradle Plugin Version 8.1.2
Gradle Version 8.4
OkHttp Version 4.9.3

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2023/11/08 14:45

URI はファイル名ではありません。そもそも file: じゃなくて content: だし…。
ak.n

2023/11/08 14:55

おっしゃる通りですね。修正しました。
guest

回答1

0

ベストアンサー

画像の選択を startActivity で Intent.ACTION_OPEN_DOCUMENT で OS に要求する等して返ってくるのは、コンテンツプロパイダ専用の (URL の形をした ) 識別子です。
その識別子と実際のファイルとの関係を知っているのはコンテンツプロバイダだけで、識別子自体は実際のファイルとは(大抵は)何の関係もありません。

画像データを取得する場合はその識別子でコンテンツリゾルバからストリームを得る等してください。

投稿2023/11/08 15:14

jimbe

総合スコア13350

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ak.n

2023/11/08 22:18

ありがとうございました。 Android のファイルシステムの理解が足りていませんでした。 様々なケースで、 Uri から、正しく実際の Path を得るのはなかなか面倒なようですが、 上手く処理が書かれた getPathFromUri() を見つけましたので、これを噛ましたところ、問題なく動きました。
jimbe

2023/11/09 03:20

>Uri から、正しく実際の Path を得るのはなかなか面倒 というよりも、そもそも path を使うな、ということのように感じます。 画像を管理する存在に対して「この画像をくれ」と言えば得られるということで、画像がどう管理されているか(画像がどこにあるか)は知らなくても良いだろうということではないでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問