Android使用Retrofit下载文件时如何获取服务器返回的原始文件名
核心诉求
我有一个可返回PDF文件的API接口,浏览器直接访问接口请求URL时会自动触发对应文件的下载,下载的文件名称并非固定值,是服务端根据URL携带的查询参数动态生成的。
目前我在Android应用内通过该接口下载文件时,只能手动指定本地存储的文件名,无法对齐浏览器的下载行为,需要让应用下载的文件直接采用服务端定义的原始文件名。
已知服务端实现说明
服务端的动态文件名是通过HTTP响应头返回的,具体实现逻辑为:
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName
现有代码实现
Retrofit 下载请求逻辑
private void initDownload(){ final OkHttpClient okHttpClient = new OkHttpClient.Builder() .readTimeout(60, TimeUnit.SECONDS) .connectTimeout(60, TimeUnit.SECONDS) .build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://../.../API/") .client(okHttpClient) .build(); RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class); Call<ResponseBody> request = retrofitInterface.downloadClientFile(8685); try { downloadFile(request.execute().body()); } catch (IOException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(),e.getMessage(),Toast.LENGTH_SHORT).show(); } }
文件落盘逻辑
当前实现存在硬编码固定文件名的问题,代码如下:
private void downloadFile(ResponseBody body) throws IOException { int count; byte data[] = new byte[1024 * 4]; long fileSize = body.contentLength(); InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8); // 此处硬编码了固定文件名,未读取服务端返回的动态名称 File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "file.pdf"); OutputStream output = new FileOutputStream(outputFile); // 剩余流写入逻辑 ... }
当前流程的核心缺陷是仅提取了响应体内容,完全没有读取存储了动态文件名的响应头字段,自然无法获取服务端定义的原始文件名。
实现路径
- 调整Retrofit接口的返回值类型,将原有的
Call<ResponseBody>改为Call<Response<ResponseBody>>,从而可以读取完整的HTTP响应头信息。 - 从响应头中提取
Content-Disposition字段的内容,解析出服务端返回的原始文件名,替换落盘逻辑中的硬编码文件名。 - 补充解析异常的兜底逻辑,比如响应头缺失、文件名带特殊字符时做适配处理,避免下载流程崩溃。
内容的提问来源于stack exchange,提问作者R_1996
相关产品推荐
相关产品推荐

