java 如何使用 Retrofit2 下载文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34156530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to download a file with Retrofit2?
提问by Mohammed Aouf Zouag
How can I downloada file(image/video)from my PHPserver using Retrofit2?
我怎样才能下载一个文件(图像/视频)从我的PHP服务器使用Retrofit2?
I wasn't able to find any resources or tutorials online on how to proceed; I found this postthat treats a certain download error on SObut it's not very clear to me. Could anyone point me to the right direction?
我无法在网上找到有关如何进行的任何资源或教程;我发现这篇文章处理了SO上的某个下载错误,但对我来说不是很清楚。有人能指出我正确的方向吗?
UPDATE:
更新:
Here is my code:
这是我的代码:
FileDownloadService.java
文件下载服务.java
public interface FileDownloadService {
@GET(Constants.UPLOADS_DIRECTORY + "/{filename}")
@Streaming
Call<ResponseBody> downloadRetrofit(@Path("filename") String fileName);
}
MainActivity.java(@Blackbelt's solution)
MainActivity.java(@Blackbelt的解决方案)
private void downloadFile(String filename) {
FileDownloadService service = ServiceGenerator
.createService(FileDownloadService.class, Constants.SERVER_IP_ADDRESS);
Call<ResponseBody> call = service.downloadRetrofit("db90408a4bb1ee65d3e09d261494a49f.jpg");
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(final Response<ResponseBody> response, Retrofit retrofit) {
try {
InputStream is = response.body().byteStream();
FileOutputStream fos = new FileOutputStream(
new File(Environment.getExternalStorageDirectory(), "image.jpg")
);
int read = 0;
byte[] buffer = new byte[32768];
while ((read = is.read(buffer)) > 0) {
fos.write(buffer, 0, read);
}
fos.close();
is.close();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Exception: " + e.toString(), Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Throwable t) {
Toast.makeText(MainActivity.this, "Failed to download file...", Toast.LENGTH_LONG).show();
}
});
}
I get a FileNotFoundExceptionwhen USB debugging is active, & a NetworkOnMainThreadExceptionwhen not.
当 USB 调试处于活动状态时,我会收到FileNotFoundException 异常,否则会收到NetworkOnMainThreadException。
MainActivity.java:(@Emanuel's solution)
MainActivity.java: (@Emanuel的溶液)
private void downloadFile(String filename) {
FileDownloadService service = ServiceGenerator
.createService(FileDownloadService.class, Constants.SERVER_IP_ADDRESS);
Call<ResponseBody> call = service.downloadRetrofit("db90408a4bb1ee65d3e09d261494a49f.jpg");
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(final Response<ResponseBody> response, Retrofit retrofit) {
Log.i(TAG, "external storage = " + (Environment.getExternalStorageState() == null));
Toast.makeText(MainActivity.this, "Downloading file... " + Environment.getExternalStorageDirectory(), Toast.LENGTH_LONG).show();
File file = new File(Environment.getDataDirectory().toString() + "/aouf/image.jpg");
try {
file.createNewFile();
Files.asByteSink(file).write(response.body().bytes());
} catch (Exception e) {
Toast.makeText(MainActivity.this,
"Exception: " + e.toString(),
Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Throwable t) {
Toast.makeText(MainActivity.this, "Failed to download file...", Toast.LENGTH_LONG).show();
}
});
}
I get a FileNotFoundException.
我得到一个FileNotFoundException。
采纳答案by Emanuel Seidinger
This is a little example showing how to download the Retrofit JAR file. You can adapt it to your needs.
这是一个显示如何下载 Retrofit JAR 文件的小示例。您可以根据自己的需要进行调整。
This is the interface:
这是界面:
import com.squareup.okhttp.ResponseBody;
import retrofit.Call;
import retrofit.http.GET;
import retrofit.http.Path;
interface RetrofitDownload {
@GET("/maven2/com/squareup/retrofit/retrofit/2.0.0-beta2/{fileName}")
Call<ResponseBody> downloadRetrofit(@Path("fileName") String fileName);
}
And this is a Java class using the interface:
这是一个使用接口的 Java 类:
import com.google.common.io.Files;
import com.squareup.okhttp.ResponseBody;
import retrofit.Call;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import java.io.File;
import java.io.IOException;
public class Main {
public static void main(String... args) {
Retrofit retrofit = new Retrofit.Builder().
baseUrl("http://repo1.maven.org").
build();
RetrofitDownload retrofitDownload = retrofit.create(RetrofitDownload.class);
Call<ResponseBody> call = retrofitDownload.downloadRetrofit("retrofit-2.0.0-beta2.jar");
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofitParam) {
File file = new File("retrofit-2.0.0-beta2.jar");
try {
file.createNewFile();
Files.asByteSink(file).write(response.body().bytes());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Throwable t) {
}
});
}
}
回答by Ivan Milisavljevic
If anybody stumbles upon this response this is how i did it using retrofit in conjunction with Rx. Every downloaded file is cached, and any subsequent requests with the same url will return the already downloaded file.
如果有人偶然发现此响应,这就是我将改造与 Rx 结合使用的方式。每个下载的文件都会被缓存,任何具有相同 url 的后续请求都将返回已下载的文件。
In order to use this just subscribe to this observable and pass your url. This will save your file in downloads directory so make sure to ask for permissions if your app targets API 23 or greater.
为了使用它,只需订阅这个 observable 并传递你的 url。这会将您的文件保存在下载目录中,因此如果您的应用面向 API 23 或更高版本,请确保请求权限。
public Observable<File> getFile(final String filepath) {
URL url = null;
try {
url = new URL(filepath);
} catch (MalformedURLException e) {
e.printStackTrace();
}
final String name = url.getPath().substring(url.getPath().lastIndexOf("/") + 1);
final File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), name);
if (file.exists()) {
return Observable.just(file);
} else {
return mRemoteService.getFile(filepath).flatMap(new Func1<Response<ResponseBody>, Observable<File>>() {
@Override
public Observable<File> call(final Response<ResponseBody> responseBodyResponse) {
return Observable.create(new Observable.OnSubscribe<File>() {
@Override
public void call(Subscriber<? super File> subscriber) {
try {
final File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsoluteFile(), name);
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeAll(responseBodyResponse.body().source());
sink.flush();
sink.close();
subscriber.onNext(file);
subscriber.onCompleted();
file.deleteOnExit();
} catch (IOException e) {
Timber.e("Save pdf failed with error %s", e.getMessage());
subscriber.onError(e);
}
}
});
}
});
}
}
Retrofit part of the call
改造部分通话
@Streaming
@GET
Observable<retrofit2.Response<ResponseBody>> getFile(@Url String fileUrl);
回答by Blackbelt
to downloada file, you might want the raw InputStream
of the response and write is content on the sdcard
. To do so, you should use ResponseBodyas T
for your return type, Call<ResponseBody>
. You will then use Retrofit
to enqueue
a
要下载文件,您可能需要原始InputStream
响应并写入sdcard
. 为此,您应该使用ResponseBody作为T
您的返回类型,Call<ResponseBody>
. 然后,您将使用Retrofit
到enqueue
一个
Callback<ResponseBody>
and when the onResponse
当 onResponse
@Override
public void onResponse(final Response<ResponseBody> response, Retrofit retrofit) {
is invoked, you can retrieve the InputStream
, with response.byteStream()
, read from it, and write what you read on the sdcard (have a look here)
被调用,您可以检索InputStream
, with response.byteStream()
,从中读取,并将您读到的内容写入 sdcard (看看这里)