溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

android+spring boot 選擇,上傳,下載文件

發(fā)布時(shí)間:2020-07-28 22:12:02 來源:網(wǎng)絡(luò) 閱讀:321 作者:qq5d1070a92e32e 欄目:建站服務(wù)器

1 概述

前端android,上傳與下載文件,使用OkHttp處理請(qǐng)求,后端使用spring boot+MVC,處理android發(fā)送來的上傳與下載請(qǐng)求.這個(gè)其實(shí)不難,就是特別多奇奇怪怪的坑,因此,希望看到的,不要像筆者這樣踩的那么痛苦了...

2 環(huán)境

  • win10
  • Spring Boot 2.2.2 RELEASE
  • IDEA 2019.3.1
  • Android Studio 3.6RC1
  • Tomcat 9.0.30

3 android

3.1 準(zhǔn)備工作

3.1.1 新建工程

這次用一個(gè)全新的例子寫博客,因此從新建工程開始:

android+spring boot 選擇,上傳,下載文件

android+spring boot 選擇,上傳,下載文件

3.1.2 AndroidManifest.xml

加入

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:usesCleartextTraffic="true">

網(wǎng)絡(luò)權(quán)限,讀寫SD卡權(quán)限,當(dāng)然還有允許http請(qǐng)求的權(quán)限.

3.1.3 build.gradle

加入

compileOptions {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}

這個(gè)是支持JDK8的.
還有這兩個(gè)okhttp與conscrypt,最新版本okhttp可以在這里查看,最新版本conscrypt在這里:

implementation 'com.squareup.okhttp3:okhttp:4.3.1'
implementation 'org.conscrypt:conscrypt-android:2.2.1'

3.1.4 上傳文件

手動(dòng)上傳一些文件到AVD設(shè)備,為下一步選擇與上傳文件做準(zhǔn)備,先把這個(gè)窗口工具欄打開:

android+spring boot 選擇,上傳,下載文件

打開后,打開在右側(cè)欄中的Device File Explorer:

android+spring boot 選擇,上傳,下載文件

然后選擇sdcard文件夾上傳文件即可,其他文件夾一般沒有權(quán)限.

android+spring boot 選擇,上傳,下載文件

3.1.5 布局

添加三個(gè)button(上傳/下載/選擇文件),一個(gè)EditText(上傳文件名與下載文件名),一個(gè)ImageView(顯示下載的圖片).

android+spring boot 選擇,上傳,下載文件

直接拖放改一下id.

3.2 選擇文件

3.2.1 申請(qǐng)權(quán)限

首先申請(qǐng)動(dòng)態(tài)讀寫文件權(quán)限(其實(shí)選擇文件只需要讀權(quán)限,因?yàn)楹竺娴南螺d需要寫權(quán)限所以這里就一起申請(qǐng)了):

android+spring boot 選擇,上傳,下載文件

使用checkSelfPermission檢查權(quán)限,參數(shù)為一個(gè)Context與String,String表示相應(yīng)的權(quán)限,如果有了這個(gè)權(quán)限就會(huì)返回

PackageManager.PERMISSION_GRANTED

沒有就會(huì)返回

PackageManager.PERMISSION_DENIED

沒有就利用requestPermissions()申請(qǐng),參數(shù)為Content,String[],int,String[]表示要申請(qǐng)的所有權(quán)限,int是一個(gè)requestCode.

3.2.2 Intent選擇文件

android+spring boot 選擇,上傳,下載文件

新建一個(gè)Intent后,設(shè)置選擇類型,然后就重寫onActivityResult:

android+spring boot 選擇,上傳,下載文件

這是簡(jiǎn)化了的處理,因?yàn)檫x擇的是圖片,選擇其他文件的話可以參照這里.

其中path是選擇的文件的路徑,可能你會(huì)問:

String path = dir.toString().substring(0,dir.toString().indexOf("0")+2) +
    DocumentsContract.getDocumentId(uri).split(":")[1];

這個(gè)是怎么來的,其實(shí)是拼湊過來的,因?yàn)檫@是圖片,是這個(gè)的簡(jiǎn)化版:

android+spring boot 選擇,上傳,下載文件

(博客在這里)

3.3 上傳文件

android+spring boot 選擇,上傳,下載文件

參數(shù)為文件路徑與文件名,然后使用OkHttpClient,因?yàn)槭俏募?用的body是MultipartBody,增加一個(gè)叫file的FormDataPart與一個(gè)叫filename的FormDataPart.然后使用execute()發(fā)送請(qǐng)求,body()獲取響應(yīng)內(nèi)容,這里假設(shè)了后端響應(yīng)一個(gè)布爾,表示上傳成功或失敗,url的話使用了本地的路徑,注意不能是localhost,使用內(nèi)網(wǎng)ip,然后還要與后端對(duì)應(yīng).

3.4 下載文件

android+spring boot 選擇,上傳,下載文件

參數(shù)為一個(gè)文件名,根據(jù)這個(gè)文件名返回對(duì)應(yīng)的文件,返回一個(gè)File,這里請(qǐng)求體可以選擇FormBody或MultipartBody,因?yàn)檫@是一個(gè)文件名參數(shù),這里筆者為了統(tǒng)一就選擇了MultipartBody,使用FormBody的話,只需要將RequestBody的那一行改為:

RequestBody body = new FormBody.Builder().add("filename",filename).build();

有了請(qǐng)求體后發(fā)送請(qǐng)求獲取響應(yīng)體,進(jìn)而獲取輸入流,然后首先需要判斷是否為空,但不能直接這樣判斷:

inputStream == null

因?yàn)楹蠖耸沁@樣的:

android+spring boot 選擇,上傳,下載文件

從響應(yīng)體獲取的inputStream肯定不為null,需要先進(jìn)行一次讀取(也就是判斷里面的文件是否為null),若為null的話刪除這個(gè)文件,不為null的話繼續(xù)讀取并寫入文件.

4 Spring Boot

4.1 準(zhǔn)備工作

用的是IDEA,其他IDE請(qǐng)自行搜索如何新建一個(gè)SpringBoot工程.

4.1.1 新建工程

android+spring boot 選擇,上傳,下載文件

打包的話可以jar或war,不用部署的話jar即可,要部署的話后期也可以改成war.

android+spring boot 選擇,上傳,下載文件

兩個(gè),一個(gè)Spring Web,用于MVC等,一個(gè)模板引擎,用于顯示視圖,如果不需要顯示可以不選.

android+spring boot 選擇,上傳,下載文件

4.1.2 application.properties

作為一個(gè)示例demo,屬性就直接在application.properties中配置了,實(shí)際情況請(qǐng)?jiān)谙鄳?yīng)的配置文件中配置相應(yīng)屬性.

android+spring boot 選擇,上傳,下載文件

需要配置上傳文件的大小限制與上傳文件夾的路徑.

4.1.3 pom.xml

這里其實(shí)不需要干什么,只是如果下載依賴慢的話,可以這樣設(shè)置settings.xml文件,在<mirrors>中加上:

<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>

<mirror>
    <id>uk</id>
    <mirrorOf>central</mirrorOf>
    <name>Human Readable Name for this Mirror.</name>
    <url>http://uk.maven.org/maven2/</url>
</mirror>

<mirror>
    <id>CN</id>
    <name>OSChina Central</name>
    <url>http://maven.oschina.net/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
</mirror>

<mirror>
    <id>nexus</id>
    <name>internal nexus repository</name>
    <!-- <url>http://192.168.1.100:8081/nexus/content/groups/public/</url>-->
    <url>http://repo.maven.apache.org/maven2</url>
    <mirrorOf>central</mirrorOf>
</mirror>

windows用戶的話這個(gè)文件在

C:\Users\{username}\.m2\settings.xml

linux的話在

~/.m2/settings.xml

4.2 處理上傳文件

android+spring boot 選擇,上傳,下載文件

首先對(duì)應(yīng)的post映射路徑為/upload,與android端的路徑對(duì)應(yīng),然后需要一個(gè)表示文件的MultipartFile與一個(gè)表示文件名的String,判斷這兩個(gè)是否為空后,如果上傳的文件夾不存在則先創(chuàng)建,存在的話直接進(jìn)行復(fù)制,然后根據(jù)復(fù)制成功或失敗返回布爾值.復(fù)制使用了Files.copy(),第一個(gè)InputStream為上傳文件的輸入流,第二個(gè)Path為存儲(chǔ)文件的路徑,resolve(filename)相當(dāng)于在上傳目錄下的filename文件.輸出的話建議使用日志代替.

4.3 處理下載文件

下載的話可以選擇使用get或post請(qǐng)求,這里選擇了post請(qǐng)求,因?yàn)閍ndroid端是post請(qǐng)求,需要對(duì)應(yīng).get請(qǐng)求的話可以從瀏覽器發(fā)起.

android+spring boot 選擇,上傳,下載文件

首先根據(jù)文件名獲取對(duì)應(yīng)文件,判斷文件是否存在后返回一個(gè)ResponseEntity,需要設(shè)定content-type與body,content-type根據(jù)需要設(shè)置即可,這里是圖片,默認(rèn).jpg或.png,body的話使用FileSystemResource,直接new一個(gè)放進(jìn)body即可.

如果不存在相應(yīng)的文件則返回null,這里需要注意一下前端的判斷,不能直接判斷ResponseBody是否為null.

5 測(cè)試

5.1 postman測(cè)試

postman只能測(cè)試與后端的連接,上傳等是否有問題,可以用來定位后端的問題.

5.1.1 上傳測(cè)試

再Headers中設(shè)置了Content-Type為multipart/form-data后:

android+spring boot 選擇,上傳,下載文件

在body添加一個(gè)叫file的文件與一個(gè)叫filename的字符串表示文件名:

android+spring boot 選擇,上傳,下載文件

發(fā)送,返回true.

android+spring boot 選擇,上傳,下載文件

服務(wù)器端有輸出提示:

android+spring boot 選擇,上傳,下載文件

查看文件夾:

android+spring boot 選擇,上傳,下載文件

5.1.2 下載測(cè)試

把file參數(shù)關(guān)掉,保留filename,修改路徑.

android+spring boot 選擇,上傳,下載文件

然后發(fā)送,postman可以直接顯示圖片:

android+spring boot 選擇,上傳,下載文件

5.2 android端測(cè)試

5.2.1 上傳測(cè)試

android+spring boot 選擇,上傳,下載文件

后端提示:

android+spring boot 選擇,上傳,下載文件

查看文件夾:

android+spring boot 選擇,上傳,下載文件

5.2.2 下載測(cè)試

輸入文件名后直接下載:

android+spring boot 選擇,上傳,下載文件

默認(rèn)的話是放在這里,按需要更改位置即可,注意加上寫權(quán)限:

android+spring boot 選擇,上傳,下載文件

若看不到文件選擇synchronize即可.

android+spring boot 選擇,上傳,下載文件

6 部署到服務(wù)器

服務(wù)器用的是tomcat,需要修改一些Spring Boot的部分.

6.1 部署

6.1.1 改變打包方式

pom.xml中jar改成war.

android+spring boot 選擇,上傳,下載文件

6.1.2 去除tomcat依賴

pom.xml加入:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

6.1.3 修改Main

修改Main類,讓其繼承SpringBootServletInitializer,重載configure(),同時(shí)main()保持不變.

修改前:

android+spring boot 選擇,上傳,下載文件

修改后:

android+spring boot 選擇,上傳,下載文件

6.1.4 修改路徑

這個(gè)按需要修改即可,在這里不需要,注意就是@PostMapping,@GetMapping等都是相對(duì)于

tomcat/webapps/項(xiàng)目/

目錄下的.

6.1.5 設(shè)置打包名字

build加上<finalName>.

android+spring boot 選擇,上傳,下載文件

6.1.6 打包

android+spring boot 選擇,上傳,下載文件

6.1.7 上傳到服務(wù)器

打包后的文件放在target下,使用scp上傳即可,這里是本地的tomcat,就這接移動(dòng)war了.

6.1.8 運(yùn)行

開啟tomcat,雙擊startup.bat即可.

android+spring boot 選擇,上傳,下載文件

linux的話:

cd xxxx/tomcat/bin
./startup.sh

6.2 測(cè)試

在測(cè)試前需要確保沒有占用相應(yīng)端口,默認(rèn)8080,也就是說,如果不改端口的話,需要關(guān)閉IDEA運(yùn)行中的SpringBoot應(yīng)用.

6.2.1 postman測(cè)試

上傳測(cè)試,注意需要改路徑,加上打包項(xiàng)目名,ip的話可以使用localhost或者內(nèi)網(wǎng)ip.

android+spring boot 選擇,上傳,下載文件

服務(wù)器這邊收到了,因?yàn)樯蟼髀窂街皇侵苯訉懨?因此會(huì)與startup.bat同一路徑.

android+spring boot 選擇,上傳,下載文件

下載測(cè)試:

android+spring boot 選擇,上傳,下載文件

服務(wù)器的輸出:

android+spring boot 選擇,上傳,下載文件

6.2.2 android端測(cè)試

android端需要修改路徑即可,加上war打包的名字.

android+spring boot 選擇,上傳,下載文件

這里打包的名字是kr,直接加上即可.

android+spring boot 選擇,上傳,下載文件

上傳那里也是要加上,然后:

android+spring boot 選擇,上傳,下載文件

服務(wù)器的輸出:

android+spring boot 選擇,上傳,下載文件

查看文件:

android+spring boot 選擇,上傳,下載文件

7 最最最喜歡的

7.1 權(quán)限

android需要讀權(quán)限才能讀取文件并上傳,需要寫權(quán)限才能保存從服務(wù)器返回的文件,在AndroidManifest.xml中加入:

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

這是外部設(shè)備的讀寫權(quán)限.當(dāng)然,加入這個(gè)還不能訪問,因?yàn)?android6.0以后還需要?jiǎng)討B(tài)申請(qǐng)權(quán)限,所以:

String [] permission = new String[]{
    "android.permission.READ_EXTERNAL_STORAGE",
    "android.permission.WRITE_EXTERNAL_STORAGE"
};
if(
    ActivityCompat.checkSelfPermission(this,permission[0]) != PackageManager.PERMISSION_GRANTED
    ||
    ActivityCompat.checkSelfPermission(this,permission[1]) != PackageManager.PERMISSION_DENIED
)
{
    ActivityCompat.requestPermissions(this,permission,1);
}

7.2 路徑

需要保證下面幾個(gè)路徑正確,還有可讀,可寫等:

  • url路徑不能錯(cuò).
  • 前端上傳文件的路徑.
  • 后端接收前端上傳文件的路徑.
  • 后端發(fā)送前端需要下載的文件的路徑.
  • 前端接收下載文件的路徑.

7.3 有關(guān)http的問題

7.3.1 okhttp的stream關(guān)閉

android+spring boot 選擇,上傳,下載文件

若前端是這樣寫的,在工具類中返回了之后Response已經(jīng)關(guān)閉,因此需要讀取輸入流之類的需要先讀取再返回,而不是返回一個(gè)ResponseBody或InputStream進(jìn)行讀取,否則會(huì)提示"closed".

7.3.2 http

Android P開始默認(rèn)禁用http,因此可以使用https或者在AndroidManifest.xml中允許http連接:

<application android:usesCleartextTraffic="true">

7.3.3 線程

網(wǎng)絡(luò)請(qǐng)求不能在主線程中,新開一個(gè)線程即可.

7.3.4 AVD

若檢查過了服務(wù)器與android端沒問題,那么有可能是AVD的問題,解決方法很簡(jiǎn)單,卸載,重啟AVD,注意一定要卸載再重啟.

7.4 ip

在本地測(cè)試的話后端可以直接localhost,在android端不能直接localhost,可以使用ipconfig或ifconfig查看內(nèi)網(wǎng)ip,輸入內(nèi)網(wǎng)ip即可.

android+spring boot 選擇,上傳,下載文件

若在服務(wù)器上測(cè)試直接使用服務(wù)器ip.

7.5 判空處理

對(duì)于前端,應(yīng)該判斷存儲(chǔ)路徑是否為空,是否為null等,再傳給后端,對(duì)于后端,要判斷文件是否存在等,不存在就返回null,這時(shí)又需要前端進(jìn)行判斷返回的null,在下載文件時(shí),雖然對(duì)不存在的文件后端返回null,但是,前端收到的是一個(gè)InputStream,不能直接判斷是否為null,需要先讀取一次,再進(jìn)行剩下的讀取:

android+spring boot 選擇,上傳,下載文件

8 源碼

github

碼云

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI