如果你只是在找retrofit怎么使用formdata格式上传图片,请直接看最后一个函数和retrofit代码,有什么不懂直接留言交流吧!!我也是小白
在android中调用相机拍摄图片,并通过post上传图片到服务器是一个很常见的需求。
下面介绍一下我的实现方法:
在给予相机权限后,将拍摄的图片通过retrofit post上传至服务器,这里是使用form-data的post格式
下面看代码:我使用kotlin实现,java类似:
权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
upload是一个按钮,用来调用相机拍照
upload.setOnClickListener {
reqPermissions()
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent , 100)
}
下面是他用到的方法:
fun reqPermissions(){
var permission = listOf(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
)
permission.forEach {
if (ActivityCompat.checkSelfPermission(this,
it
) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions( this, arrayOf(it),100)
}
}
}
override fun onActivityResult(requestCode : Int , resultCode : Int , data : Intent?) {
super.onActivityResult(requestCode , resultCode , data)
val extras = data?.extras
var bitmap=extras?.get("data")
println(bitmap.toString())
if (bitmap!=null){
var progressdig=ProgressDialog(this@LoginActivity)
progressdig.setTitle("提示")
progressdig.setMessage("正在准备上传图片")
progressdig.setCancelable(false)
progressdig.show()
BitmapUtils.saveBitmap(imgName,bitmap as Bitmap,this@LoginActivity)
progressdig.dismiss()
upload.setImageBitmap(bitmap)
}else{
println("else")
}
}
object FileUtils {
/**
* 判断指定目录的文件夹是否存在,如果不存在则需要创建新的文件夹
* @param fileName 指定目录
* @return 返回创建结果 TRUE or FALSE
*/
fun fileIsExist(fileName : String?) : Boolean {
//传入指定的路径,然后判断路径是否存在
val file = File(fileName)
return if (file.exists()) true else {
//file.mkdirs() 创建文件夹的意思
file.mkdirs()
}
}
}
// 保存bitmap到file
object BitmapUtils {
/**
* Save Bitmap
*
* @param name file name
* @param bm picture to save
*/
fun saveBitmap(name : String , bm : Bitmap , mContext : Context) {
val TargetPath : String = mContext.getFilesDir().toString() + "/images/"
//判断指定文件夹的路径是否存在
if (! fileIsExist(TargetPath)) {
Log.d("Save Bitmap" , "TargetPath isn't exist")
}
//如果指定文件夹创建成功,那么我们则需要进行图片存储操作
val saveFile = File(TargetPath , name)
try {
val saveImgOut = FileOutputStream(saveFile)
// compress - 压缩的意思
bm.compress(Bitmap.CompressFormat.JPEG , 100 , saveImgOut)
//存储完成后需要清除相关的进程
saveImgOut.flush()
saveImgOut.close()
Log.d("Save Bitmap" , "The picture is save to your phone!")
} catch (ex : IOException) {
ex.printStackTrace()
}
}
}
经过上面就已经拍摄到图片,下面开始上传
retrofit的代码:
interface Apis{
@POST("loginin/")
@FormUrlEncoded
fun login(@FieldMap maps : Map<String , String>) : retrofit2.Call<User>
}
object NetClient{
var client: OkHttpClient
var retrofitCli: Retrofit
val apis:Apis
init {
val inter= HttpLoggingInterceptor()
inter.setLevel(HttpLoggingInterceptor.Level.BODY)
client = OkHttpClient.Builder() //builder构造者设计模式
.connectTimeout(10, TimeUnit.SECONDS) //连接超时时间
.readTimeout(10, TimeUnit.SECONDS) //读取超时
.writeTimeout(10, TimeUnit.SECONDS) //写超时,也就是请求超时
.addInterceptor(inter)
.build()
retrofitCli= Retrofit.Builder()
.client(client)
.baseUrl("http://120.76.201.116:8888/apis/") //改成你的api链接
.addConverterFactory(GsonConverterFactory.create())
.build()
apis= retrofitCli.create(Apis::class.java)
}
}
data class User(
val code: Int,
val `data`: Data
)
下面就是上传图片的函数:
fun uploadRegister(username:String,password:String){
val builder : MultipartBody.Builder = MultipartBody.Builder()
.setType(MultipartBody.FORM) //在这里添加服务器除了文件之外的其他参数
.addFormDataPart("username" , username)
.addFormDataPart("password" , password)
var file1Location=this.getFilesDir().toString() + "/images/"+imgName
val file = File(file1Location)
val imageBody : RequestBody = RequestBody.create(
"multipart/form-data".toMediaTypeOrNull() ,
file
)
//添加文件(uploadfile就是你服务器中需要的文件参数)
builder.addFormDataPart("faceImg" , file.name , imageBody)
val parts= builder.build().parts
NetClient.apis.createUser(parts).enqueue(object:Callback<User>{
override fun onResponse(call : Call<User> , response : Response<User>) {
var res=response.body()
if (res!=null && res.code==200){
backHome(res.data) //换成你需要的
}
}
override fun onFailure(call : Call<User> , t : Throwable) {
Toast.makeText(this@LoginActivity,"network error", Toast.LENGTH_SHORT).show()
}
})
}