android+spring boot 选择,上传,下载文件

1 概述

前端android,上传与下载文件,使用OkHttp处理请求,后端使用spring boot+MVC,处理android发送来的上传与下载请求.这个其实不难,就是特别多奇奇怪怪的坑,因此,希望看到的,不要像笔者这样踩的那么痛苦了...

2 环境

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

3 android

3.1 准备工作

3.1.1 新建工程

这次用一个全新的例子写博客,因此从新建工程开始:

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">

网络权限,读写SD卡权限,当然还有允许http请求的权限.

3.1.3 build.gradle

加入

compileOptions {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
}

这个是支持JDK8的.
还有这两个okhttp与conscrypt,最新版本okhttp可以在这里查看,最新版本conscrypt在这里:

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

3.1.4 上传文件

手动上传一些文件到AVD设备,为下一步选择与上传文件做准备,先把这个窗口工具栏打开:

打开后,打开在右侧栏中的Device File Explorer:

然后选择sdcard文件夹上传文件即可,其他文件夹一般没有权限.

3.1.5 布局

添加三个button(上传/下载/选择文件),一个EditText(上传文件名与下载文件名),一个ImageView(显示下载的图片).

直接拖放改一下id.

3.2 选择文件

3.2.1 申请权限

首先申请动态读写文件权限(其实选择文件只需要读权限,因为后面的下载需要写权限所以这里就一起申请了):

使用checkSelfPermission检查权限,参数为一个Context与String,String表示相应的权限,如果有了这个权限就会返回

PackageManager.PERMISSION_GRANTED

没有就会返回

PackageManager.PERMISSION_DENIED

没有就利用requestPermissions()申请,参数为Content,String[],int,String[]表示要申请的所有权限,int是一个requestCode.

3.2.2 Intent选择文件

新建一个Intent后,设置选择类型,然后就重写onActivityResult:

这是简化了的处理,因为选择的是图片,选择其他文件的话可以参照这里.

其中path是选择的文件的路径,可能你会问:

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

这个是怎么来的,其实是拼凑过来的,因为这是图片,是这个的简化版:

(博客在这里)

3.3 上传文件

参数为文件路径与文件名,然后使用OkHttpClient,因为是文件,用的body是MultipartBody,增加一个叫file的FormDataPart与一个叫filename的FormDataPart.然后使用execute()发送请求,body()获取响应内容,这里假设了后端响应一个布尔,表示上传成功或失败,url的话使用了本地的路径,注意不能是localhost,使用内网ip,然后还要与后端对应.

3.4 下载文件

参数为一个文件名,根据这个文件名返回对应的文件,返回一个File,这里请求体可以选择FormBody或MultipartBody,因为这是一个文件名参数,这里笔者为了统一就选择了MultipartBody,使用FormBody的话,只需要将RequestBody的那一行改为:

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

有了请求体后发送请求获取响应体,进而获取输入流,然后首先需要判断是否为空,但不能直接这样判断:

inputStream == null

因为后端是这样的:

从响应体获取的inputStream肯定不为null,需要先进行一次读取(也就是判断里面的文件是否为null),若为null的话删除这个文件,不为null的话继续读取并写入文件.

4 Spring Boot

4.1 准备工作

用的是IDEA,其他IDE请自行搜索如何新建一个SpringBoot工程.

4.1.1 新建工程

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

两个,一个Spring Web,用于MVC等,一个模板引擎,用于显示视图,如果不需要显示可以不选.

4.1.2 application.properties

作为一个示例demo,属性就直接在application.properties中配置了,实际情况请在相应的配置文件中配置相应属性.

需要配置上传文件的大小限制与上传文件夹的路径.

4.1.3 pom.xml

这里其实不需要干什么,只是如果下载依赖慢的话,可以这样设置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用户的话这个文件在

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

linux的话在

~/.m2/settings.xml

4.2 处理上传文件

首先对应的post映射路径为/upload,与android端的路径对应,然后需要一个表示文件的MultipartFile与一个表示文件名的String,判断这两个是否为空后,如果上传的文件夹不存在则先创建,存在的话直接进行复制,然后根据复制成功或失败返回布尔值.复制使用了Files.copy(),第一个InputStream为上传文件的输入流,第二个Path为存储文件的路径,resolve(filename)相当于在上传目录下的filename文件.输出的话建议使用日志代替.

4.3 处理下载文件

下载的话可以选择使用get或post请求,这里选择了post请求,因为android端是post请求,需要对应.get请求的话可以从浏览器发起.

首先根据文件名获取对应文件,判断文件是否存在后返回一个ResponseEntity,需要设定content-type与body,content-type根据需要设置即可,这里是图片,默认.jpg或.png,body的话使用FileSystemResource,直接new一个放进body即可.

如果不存在相应的文件则返回null,这里需要注意一下前端的判断,不能直接判断ResponseBody是否为null.

5 测试

5.1 postman测试

postman只能测试与后端的连接,上传等是否有问题,可以用来定位后端的问题.

5.1.1 上传测试

再Headers中设置了Content-Type为multipart/form-data后:

在body添加一个叫file的文件与一个叫filename的字符串表示文件名:

发送,返回true.

服务器端有输出提示:

查看文件夹:

5.1.2 下载测试

把file参数关掉,保留filename,修改路径.

然后发送,postman可以直接显示图片:

5.2 android端测试

5.2.1 上传测试

后端提示:

查看文件夹:

5.2.2 下载测试

输入文件名后直接下载:

默认的话是放在这里,按需要更改位置即可,注意加上写权限:

若看不到文件选择synchronize即可.

6 部署到服务器

服务器用的是tomcat,需要修改一些Spring Boot的部分.

6.1 部署

6.1.1 改变打包方式

pom.xml中jar改成war.

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(),同时main()保持不变.

修改前:

修改后:

6.1.4 修改路径

这个按需要修改即可,在这里不需要,注意就是@PostMapping,@GetMapping等都是相对于

tomcat/webapps/项目/

目录下的.

6.1.5 设置打包名字

build加上<finalName>.

6.1.6 打包

6.1.7 上传到服务器

打包后的文件放在target下,使用scp上传即可,这里是本地的tomcat,就这接移动war了.

6.1.8 运行

开启tomcat,双击startup.bat即可.

linux的话:

cd xxxx/tomcat/bin
./startup.sh

6.2 测试

在测试前需要确保没有占用相应端口,默认8080,也就是说,如果不改端口的话,需要关闭IDEA运行中的SpringBoot应用.

6.2.1 postman测试

上传测试,注意需要改路径,加上打包项目名,ip的话可以使用localhost或者内网ip.

服务器这边收到了,因为上传路径只是直接写名字,因此会与startup.bat同一路径.

下载测试:

服务器的输出:

6.2.2 android端测试

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

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

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

服务器的输出:

查看文件:

7 最最最喜欢的

7.1 权限

android需要读权限才能读取文件并上传,需要写权限才能保存从服务器返回的文件,在AndroidManifest.xml中加入:

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

这是外部设备的读写权限.当然,加入这个还不能访问,因为,android6.0以后还需要动态申请权限,所以:

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 路径

需要保证下面几个路径正确,还有可读,可写等:

  • url路径不能错.
  • 前端上传文件的路径.
  • 后端接收前端上传文件的路径.
  • 后端发送前端需要下载的文件的路径.
  • 前端接收下载文件的路径.

7.3 有关http的问题

7.3.1 okhttp的stream关闭

若前端是这样写的,在工具类中返回了之后Response已经关闭,因此需要读取输入流之类的需要先读取再返回,而不是返回一个ResponseBody或InputStream进行读取,否则会提示"closed".

7.3.2 http

Android P开始默认禁用http,因此可以使用https或者在AndroidManifest.xml中允许http连接:

<application android:usesCleartextTraffic="true">

7.3.3 线程

网络请求不能在主线程中,新开一个线程即可.

7.3.4 AVD

若检查过了服务器与android端没问题,那么有可能是AVD的问题,解决方法很简单,卸载,重启AVD,注意一定要卸载再重启.

7.4 ip

在本地测试的话后端可以直接localhost,在android端不能直接localhost,可以使用ipconfig或ifconfig查看内网ip,输入内网ip即可.

若在服务器上测试直接使用服务器ip.

7.5 判空处理

对于前端,应该判断存储路径是否为空,是否为null等,再传给后端,对于后端,要判断文件是否存在等,不存在就返回null,这时又需要前端进行判断返回的null,在下载文件时,虽然对不存在的文件后端返回null,但是,前端收到的是一个InputStream,不能直接判断是否为null,需要先读取一次,再进行剩下的读取:

8 源码

github

码云

原文地址:https://blog.51cto.com/14415843/2468518

时间: 2024-10-09 23:15:43

android+spring boot 选择,上传,下载文件的相关文章

Android连接socket服务器上传下载多个文件

android连接socket服务器上传下载多个文件1.socket服务端SocketServer.java public class SocketServer { int port = 8888;// 端口号,必须与客户端一致 // 选择进行传输的文件(测试) String path = "C:\\Temp"; String filePath = "E:\\img.png"; Socket client; public static void main(Strin

Linux上传下载文件

2种方式:xftp(工具).lrzsz xftp:协议--SFTP.端口号--22 lrzsz: rz,sz是Linux/Unix同Windows进行ZModem文件传输的命令行工具. 优点就是不用再开一个sftp工具登录上去上传下载文件. sz(下载):将选定的文件发送(send)到本地机器 rz(上传):运行该命令会弹出一个文件选择窗口,从本地选择文件上传到Linux服务器 安装命令:yum install lrzsz 从服务端发送文件到客户端:sz filename 从客户端上传文件到服务

向云服务器上传下载文件方法汇总(转)

转载于:https://yq.aliyun.com/articles/64700 摘要: 一.向Windows服务器上传下载文件方式 方法有很多种,此处介绍远程桌面的本地资源共享方法. 1.运行mstsc,连接远程桌面的时候,点"选项>>" 2."本地资源"-->详细信息. 3."磁盘驱动器"前面打钩. 一.向Windows服务器上传下载文件方式 方法有很多种,此处介绍远程桌面的本地资源共享方法. 1.运行mstsc,连接远程桌

向linux服务器上传下载文件方式收集

向linux服务器上传下载文件方式收集 1. scp [优点]简单方便,安全可靠:支持限速参数[缺点]不支持排除目录[用法] scp就是secure copy,是用来进行远程文件拷贝的.数据传输使用 ssh,并且和ssh 使用相同的认证方式,提供相同的安全保证 . 命令格式: scp [参数] <源地址(用户名@IP地址或主机名)>:<文件路径> <目的地址(用户名 @IP 地址或主机名)>:<文件路径> 举例: scp /home/work/source.

经验分享] 向云服务器上传下载文件方法汇总

一.向Windows服务器上传下载文件方式 方法有很多种,此处介绍远程桌面的本地资源共享方法. 1.运行mstsc,连接远程桌面的时候,点"选项>>" <ignore_js_op> 2."本地资源"-->详细信息. <ignore_js_op> 3."磁盘驱动器"前面打钩. <ignore_js_op> 4.连接远程电脑后,打开"我的电脑",就能看到刚刚共享的硬盘驱动器.把

利用 secureCRT 直接上传下载文件 (sz,rz)

在window下向linux传送文件的方法. 首先在window中安装SecureCRT,然后在快速连接中建立一个到linux的连接,当然,你要先知道你的系统的ip,在终端中键入ifconfig可以查看到. 然后连接即可登陆到linux的终端下 要从linux传文件到window的话,这需要cd到你要传的文件的目录,然后用命令:sz 文件名即可上传.文件放在securesrt/download下面 要从window传送文件到linux,则在终端中输入rz,然后会出来一个对话框让你选择文件传送的.

SecureCRT上传下载文件教程(Zmodem使用教程)

SecureCRT是一个仿真终端连接工具.它可以方便的连接SSH服务器,远程管理Linux.同时,它还能使用多种协议方便的上传下载文件.其中Zmodem是SecureCRT支持比较好的一种古老的上传下载协议. 要使用Zmodem上传下载,必须要在Linux中安装相应的软件.否则SecureCRT无法正常上传或下载.在CentOS与Debian中,这个软件的名字叫“lrzsz”.下面将介绍其安装与使用方法. 安装lrzsz(zmodem) 1 [[email protected] ~]#apt-g

rz和sz上传下载文件

安装软件包 yum install? lrzsz ? 上传文件,输入rz选择文件上传(可以按住shift键多选) # rz ? sz 下载文件到本地,选择保存文件夹 # sz dd ? xshell设置默认上传下载文件夹 原文地址:https://www.cnblogs.com/fcing/p/9382377.html

上传下载文件

上传下载文件 上传: h5中input有个type属性file,可以实现选择文件功能,accept属性可以选择显示的文件类型,默认单选,加个multiple属性可以多选 使用document.querySelector获取,获取的文件信息是不可修改的,如下 // input原生样式略丑,可以隐藏,用自定义节点触发点击事件, <input onchange="" style="display:none;" accept=".png,.jpg"