美文网首页
Android10 Retrofit图片上传

Android10 Retrofit图片上传

作者: SimpleGk | 来源:发表于2019-11-23 22:17 被阅读0次

    Android10文件存储机制修改成了沙盒模式,应用不能直接访问除了沙盒文件和公共文件以外的文件,直接使用图片绝对地址上传图片会出错,可以通过图片的Uri来上传图片

        private fun copyFromUri(uri:Uri,fileName:String,subscribe:Observer<String>){
            var cacheFile = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES)?.absolutePath+File.separator+"cache")
            if(!cacheFile.exists())
                cacheFile.exists()
            cacheFile = File(cacheFile.absolutePath + File.separator + fileName)
    
            Observable.create<String>{
                val inStream:InputStream = contentResolver.openInputStream(uri)!!
                val outStream:OutputStream = FileOutputStream(cacheFile)
                val bytes = ByteArray(1024)
                var len = -1
                try {
                    while ({len = inStream.read(bytes);len}()!=-1)
                        outStream.write(bytes,0,len)
                } catch (e: Exception) {
                    it.onError(e)
                } finally {
                    inStream.close()
                    outStream.close()
                }
                it.onNext(cacheFile.path)
                it.onComplete()
            }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscribe)
        }
    

    上传图片

        private fun onUpload(path: String){
            if ( "" != path.trim() ){
                val file = File(path)
                val body = file.asRequestBody("application/octet-stream".toMediaTypeOrNull())
                val progressBody = ProgressRequestBody(body){
                    progress.progress = it.toInt()
                }
                val part = MultipartBody.Part.createFormData("file",file.name,progressBody)
                getRetrofit().create(Api::class.java).onUpload(part)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(object : Observer<ResponseBody> {
                        override fun onSubscribe(d: Disposable) {
    
                        }
    
                        override fun onNext(t: ResponseBody) {
                            Toast.makeText(this@MainActivity,"Success",Toast.LENGTH_SHORT).show()
                        }
    
                        override fun onError(e: Throwable) {
                            Toast.makeText(this@MainActivity,"Error!"+e.message,Toast.LENGTH_SHORT).show()
                        }
    
                        override fun onComplete() {
                            if(file.exists())
                                file.delete()
                        }
                    })
            }
        }
    

    网络接口定义

    @Multipart
        @POST("downloadApp/upload")
        fun onUpload(@Part part:MultipartBody.Part):Observable<ResponseBody>
    

    实现进度更新

    class ProgressRequestBody(private val requestBody: RequestBody,private val listener:((Long)->Unit) ):RequestBody() {
    
        private var byteBufferSink:BufferedSink ?= null
    
        override fun contentType(): MediaType? {
            return requestBody.contentType()
        }
    
        override fun contentLength(): Long {
            return requestBody.contentLength()
        }
    
        override fun writeTo(sink: BufferedSink) {
            if (byteBufferSink == null)
                byteBufferSink = sink(sink).buffer()
            requestBody.writeTo(byteBufferSink!!)
            byteBufferSink?.flush()
        }
    
        private fun sink(sink:Sink) = object : ForwardingSink(sink) {
    
            private var count = 0L
            private var total = -1L
    
            @SuppressLint("CheckResult")
            override fun write(source: Buffer, byteCount: Long) {
                if (total ==-1L) total = contentLength()
                super.write(source, byteCount)
                count += byteCount
                val progress = count/total.toDouble() * 100
                Observable.just(count).observeOn(AndroidSchedulers.mainThread()).subscribe {
                    listener.invoke(progress.toLong())
                }
            }
        }
    }
    

    web端的图片上传代码

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.setContentType("text/html;charset=utf-8");
    
            String realPath = userPath + "/upload/test";
            String cachePath = userPath + "/upload/cache";
    
            File realFile = new File(realPath);
            File cacheFile = new File(cachePath);
    
            System.out.println("上传路径是:"+realPath);
            if (!realFile.exists())
                realFile.mkdirs();
            if (!cacheFile.exists())
                cacheFile.mkdirs();
    
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setRepository(cacheFile);
    
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setHeaderEncoding("UTF-8");
    
            if (!ServletFileUpload.isMultipartContent(request))
                return;
    
            InputStream in = null;
            OutputStream out = null;
            List<String> files = new ArrayList<>();
            try {
                List<FileItem> items = upload.parseRequest(request);
                for (FileItem item:items){
                    if (item.isFormField()){
                        System.out.println(item.getFieldName()+": "+item.getString("UTF-8"));
                    }else {
                        String fileName = item.getName();
                        if (fileName.isEmpty()||"".equals(fileName.trim()))
                            continue;
                        fileName = fileName.substring(fileName.lastIndexOf("/")+1);
                        String downloadPath = realPath+"/"+fileName;
                        files.add(fileName);
    
                        in = item.getInputStream();
                        out = new FileOutputStream(downloadPath);
    
                        byte bt[] = new byte[1024];
    
                        int len = -1;
    
                        while ((len = in.read(bt))!=-1)
                            out.write(bt,0,len);
                    }
                    item.delete();
                }
            } catch (FileUploadException | IOException e) {
                System.out.println(e.getMessage());
                response.getWriter().write("ERROR");
            } finally {
                if (in!=null)
                    in.close();
                if (out!=null)
                    out.close();
            }
            response.getWriter().write("SUCCESS");
        }
    

    相关文章

      网友评论

          本文标题:Android10 Retrofit图片上传

          本文链接:https://www.haomeiwen.com/subject/dxrkwctx.html