如何使用 php 和 volley android 进行间接文件下载
How to do an indirect file download using php and volley android
当涉及到任何形式的 http 和 volley 连接 android 以及文件下载时,我是一个初学者,目前正在从事一个需要 android 的项目。我将文件保存在无法通过 https 直接访问以使用 volley 下载的位置。我需要使用 POST 调用 php 来强制通过 volley 下载到我的应用程序。我看过有关如何使用 HTTPCilent 信息进行强制下载的教程,但是,我的应用程序不支持使用直接 HTTPClient 调用。我们正在处理更大的文件。具体来说,我的应用程序下载为 android sceneform 生成的 sfb 文件。
我试图在 volley 向我的 php 页面发送一个字符串 POST 请求的地方使用它,该页面会回显文件的内容。但是,当我尝试显示 sfb 时,当我尝试将我的模型放在屏幕上时,我从 sceneform 得到了一个索引错误。已经验证直接存储在我的应用程序中的原始文件可以正常显示。
有谁知道如何使用 volley 进行此类下载?如果这不可能,是否有另一种不使用 HTTPClient 库的方法来做到这一点?
下面是我的代码部分,目前处理我的 php 和应用程序之间的通信:
PHP:
<?php
ini_set('display_errors',1);
$fileID = $_POST["model_id"];
$filePath = $_POST["model_path"];
$downloadPath = "<dir only this page can get to> /$fileID/$filePath";
readfile($downloadPath);
//$fileStr = file_get_contents ($downloadPath);
// echo $fileStr;
?>
Android:
private StringRequest generatePhpDownloadRequest(String FileName, String FileID)
{
StringRequest request = new StringRequest(Request.Method.POST, WebsiteInterface.DOWNLOAD_URL_STRING,
new Response.Listener<String>()
{
@Override
public void onResponse(String response) {
// response
Log.d("Response", response);
//@todo save the return information
/*if(response.length() > 60) {
createAlertDialog("LNG:" + response.substring(0, 56));
}else {
createAlertDialog(response);
}*/
if(response.length() > 10)
{
try {
if (response!=null) {
FileOutputStream outputStream;
String name=ModelInformation[0];
outputStream = openFileOutput(name, Context.MODE_PRIVATE);
outputStream.write(response.getBytes(Charset.forName("UTF-8")));
outputStream.close();
ReturnWithResult(RESULT_OK, getFilesDir().getAbsolutePath());
//Toast.makeText(this, "Download complete.", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("KEY_ERROR", "UNABLE TO DOWNLOAD FILE");
e.printStackTrace();
ReturnWithResult(RESULT_CANCELED, "KEY_ERROR: UNABLE TO DOWNLOAD FILE");
}
ReturnWithResult(RESULT_OK, getFilesDir().getAbsolutePath());
}
else
{
ReturnWithResult(RESULT_CANCELED, "invalid file");
}
//ReturnWithResult(RESULT_CANCELED, "Sucess but no file save");
}
},
new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error) {
String msg = "unknown error";
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
//This indicates that the reuest has either time out or there is no connection
//Log.d(TAG, "Connection Error!");
msg = "Connection Error!";
} else if (error instanceof AuthFailureError) {
//Error indicating that there was an Authentication Failure while performing the request
//Log.d(TAG, "Authentication Error!");
msg = "Authentication Error!";
} else if (error instanceof ServerError) {
//Indicates that the server responded with a error response
//Log.d(TAG, "Server Error!");
msg = "Server Error!";
} else if (error instanceof NetworkError) {
//Indicates that there was network error while performing the request
//Log.d(TAG, "Network Error!");
msg = "Network Error!";
} else if (error instanceof ParseError) {
// Indicates that the server response could not be parsed
//Log.d(TAG, "Parsing Error!");
msg = "Parsing Error!";
}
VolleyLog.d(TAG, "Error: " + error.getMessage());
ReturnWithResult(Activity.RESULT_CANCELED, "VOLLEY: " + msg);
}
}
) {
@Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("model_id", FileID);
params.put("model_path", FileName);
return params;
}
};
return request;
}
我建议您使用 HttpConnection 调用来下载文件负载,
这是代码,
private static final String twoHyphens = "--";
private static final String lineEnd = "\r\n";
private static final String boundary = "*****";
private String uploadFile(File sourceFile) {
HttpURLConnection.setFollowRedirects(false);
DataInputStream inStream = null;
try {
connection = (HttpURLConnection) new URL(URL_POST_MESSAGE_FILE).openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
String boundary = "---------------------------boundary";
String tail = lineEnd + "--" + boundary + "--" + lineEnd;
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
connection.setRequestProperty(modelHeader.getValue(), modelHeader.getValue());
String metadataPart = "--" + boundary + lineEnd
+ "Content-Disposition: form-data; name=\"metadata\"\r\n\r\n"
+ "" + lineEnd;
long fileLength = sourceFile.length() + tail.length();
String stringData = metadataPart + "--" + boundary + lineEnd
+ "Content-Disposition: form-data; name=\"fileToUpload\"; filename=\""
+ sourceFile.getName() + "\"\r\n"
+ "Content-Type: application/octet-stream" + lineEnd
+ "Content-Transfer-Encoding: binary" + lineEnd + "Content-length: " + fileLength + lineEnd + lineEnd;
long requestLength = stringData.length() + fileLength;
connection.setRequestProperty("Content-length", "" + requestLength);
connection.setFixedLengthStreamingMode((int) requestLength);
connection.connect();
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(stringData);
out.flush();
int bytesRead;
FileInputStream fileInputStream = new FileInputStream(sourceFile);
BufferedInputStream bufInput = new BufferedInputStream(fileInputStream);
byte buf[] = new byte[(int) sourceFile.length() / 200];
while ((bytesRead = bufInput.read(buf)) != -1) {
out.write(buf, 0, bytesRead);
out.flush();
}
out.writeBytes(tail);
out.flush();
out.close();
} catch (IOException e) {
Log.e(VolleyDownUpFiles.class.getSimpleName(), e.getMessage() + " ");
return null;
}
try {
inStream = new DataInputStream(connection.getInputStream());
String str;
if ((str = inStream.readLine()) != null) {
inStream.close();
return str;
}
} catch (IOException e) {
Log.e("Tag", e.getMessage());
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
或者更多更好的方法,
有一个库,我个人推荐给任何 android 喜欢 Light weight Volley for Api Integrations 的开发人员。
https://github.com/Lib-Jamun/Volley
dependencies {
compile 'tk.jamun:volley:0.0.4'
}
他的文档目前可用于0.0.4版本,
但是这个库的优点是 0.0.7 版本,你不需要手动解析或创建 JSON 你只需要传递你的模型 class 和其他自动完成的事情。
它的文件相关 classes 用于背景和正常使用,它对您的 Api 方法的响应非常强大,您可以获得更多东西。
我找到了一种使用 Volley 的方法。我能够使用从 here 获得的 InputStreamVollyRequest。通过将我的变量添加到参数并调用我的 php 文件,我能够成功地从我的数据库间接下载文件。下面是我现在成功执行的代码片段。 (关于我的文件路径和参数的细节已经被抽象出来)。请注意,参数似乎没有任何作用,但我抽象出了如何使用它们来确定相对文件路径。我也是如此 post 没有错误处理它只会将错误消息保存到应用程序上生成的文件中,文件名是 param1 的值。
Android: java
private InputStreamVolleyRequest generatePHPDownloadRequest(String param1Value, String param2Value)
{
Map<String,String> inParams = new HashMap<String,String>();
inParams.put("param1", param1Value);
inParams.put("param2", param2Value);
String requestURL = WebsiteInterface.DOWNLOAD_URL_STRING;
InputStreamVolleyRequest request = new InputStreamVolleyRequest(Request.Method.POST, requestURL,
new Response.Listener<byte[]>() {
@Override
public void onResponse(byte[] response) {
// TODO handle the response
try {
if (response!=null) {
FileOutputStream outputStream;
String name=param1Value;
outputStream = openFileOutput(name, Context.MODE_PRIVATE);
outputStream.write(response);
outputStream.close();
ReturnWithResult(RESULT_OK, getFilesDir().getAbsolutePath());
//Toast.makeText(this, "Download complete.", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("KEY_ERROR", "UNABLE TO DOWNLOAD FILE");
e.printStackTrace();
ReturnWithResult(RESULT_CANCELED, "KEY_ERROR: UNABLE TO DOWNLOAD FILE");
}
}
} ,new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO handle the error
error.printStackTrace();
String msg = "unknown error";
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
//This indicates that the reuest has either time out or there is no connection
//Log.d(TAG, "Connection Error!");
msg = "Connection Error!";
} else if (error instanceof AuthFailureError) {
//Error indicating that there was an Authentication Failure while performing the request
//Log.d(TAG, "Authentication Error!");
msg = "Authentication Error!";
} else if (error instanceof ServerError) {
//Indicates that the server responded with a error response
//Log.d(TAG, "Server Error!");
msg = "Server Error!";
} else if (error instanceof NetworkError) {
//Indicates that there was network error while performing the request
//Log.d(TAG, "Network Error!");
msg = "Network Error!";
} else if (error instanceof ParseError) {
// Indicates that the server response could not be parsed
//Log.d(TAG, "Parsing Error!");
msg = "Parsing Error!";
}
VolleyLog.d(TAG, "Error: " + error.getMessage());
ReturnWithResult(Activity.RESULT_CANCELED, "VOLLEY: " + msg);
}
}, (HashMap<String, String>) inParams);
return request;
}
PHP
<?php
ini_set('display_errors',1);
if(!isset($_POST["param1"]))
{
exit("PARAM 1 EMPTY");
}
if(!isset($_POST["param2"]))
{
exit("PARAM 2 EMPTY");
}
$param1Value = $_POST["param1"];
$param2Value = $_POST["param2"];
$downloadPath = "<relative path from php file location to the desired file>";
readfile($downloadPath);
?>
当涉及到任何形式的 http 和 volley 连接 android 以及文件下载时,我是一个初学者,目前正在从事一个需要 android 的项目。我将文件保存在无法通过 https 直接访问以使用 volley 下载的位置。我需要使用 POST 调用 php 来强制通过 volley 下载到我的应用程序。我看过有关如何使用 HTTPCilent 信息进行强制下载的教程,但是,我的应用程序不支持使用直接 HTTPClient 调用。我们正在处理更大的文件。具体来说,我的应用程序下载为 android sceneform 生成的 sfb 文件。
我试图在 volley 向我的 php 页面发送一个字符串 POST 请求的地方使用它,该页面会回显文件的内容。但是,当我尝试显示 sfb 时,当我尝试将我的模型放在屏幕上时,我从 sceneform 得到了一个索引错误。已经验证直接存储在我的应用程序中的原始文件可以正常显示。
有谁知道如何使用 volley 进行此类下载?如果这不可能,是否有另一种不使用 HTTPClient 库的方法来做到这一点?
下面是我的代码部分,目前处理我的 php 和应用程序之间的通信:
PHP:
<?php
ini_set('display_errors',1);
$fileID = $_POST["model_id"];
$filePath = $_POST["model_path"];
$downloadPath = "<dir only this page can get to> /$fileID/$filePath";
readfile($downloadPath);
//$fileStr = file_get_contents ($downloadPath);
// echo $fileStr;
?>
Android:
private StringRequest generatePhpDownloadRequest(String FileName, String FileID)
{
StringRequest request = new StringRequest(Request.Method.POST, WebsiteInterface.DOWNLOAD_URL_STRING,
new Response.Listener<String>()
{
@Override
public void onResponse(String response) {
// response
Log.d("Response", response);
//@todo save the return information
/*if(response.length() > 60) {
createAlertDialog("LNG:" + response.substring(0, 56));
}else {
createAlertDialog(response);
}*/
if(response.length() > 10)
{
try {
if (response!=null) {
FileOutputStream outputStream;
String name=ModelInformation[0];
outputStream = openFileOutput(name, Context.MODE_PRIVATE);
outputStream.write(response.getBytes(Charset.forName("UTF-8")));
outputStream.close();
ReturnWithResult(RESULT_OK, getFilesDir().getAbsolutePath());
//Toast.makeText(this, "Download complete.", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("KEY_ERROR", "UNABLE TO DOWNLOAD FILE");
e.printStackTrace();
ReturnWithResult(RESULT_CANCELED, "KEY_ERROR: UNABLE TO DOWNLOAD FILE");
}
ReturnWithResult(RESULT_OK, getFilesDir().getAbsolutePath());
}
else
{
ReturnWithResult(RESULT_CANCELED, "invalid file");
}
//ReturnWithResult(RESULT_CANCELED, "Sucess but no file save");
}
},
new Response.ErrorListener()
{
@Override
public void onErrorResponse(VolleyError error) {
String msg = "unknown error";
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
//This indicates that the reuest has either time out or there is no connection
//Log.d(TAG, "Connection Error!");
msg = "Connection Error!";
} else if (error instanceof AuthFailureError) {
//Error indicating that there was an Authentication Failure while performing the request
//Log.d(TAG, "Authentication Error!");
msg = "Authentication Error!";
} else if (error instanceof ServerError) {
//Indicates that the server responded with a error response
//Log.d(TAG, "Server Error!");
msg = "Server Error!";
} else if (error instanceof NetworkError) {
//Indicates that there was network error while performing the request
//Log.d(TAG, "Network Error!");
msg = "Network Error!";
} else if (error instanceof ParseError) {
// Indicates that the server response could not be parsed
//Log.d(TAG, "Parsing Error!");
msg = "Parsing Error!";
}
VolleyLog.d(TAG, "Error: " + error.getMessage());
ReturnWithResult(Activity.RESULT_CANCELED, "VOLLEY: " + msg);
}
}
) {
@Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("model_id", FileID);
params.put("model_path", FileName);
return params;
}
};
return request;
}
我建议您使用 HttpConnection 调用来下载文件负载, 这是代码,
private static final String twoHyphens = "--";
private static final String lineEnd = "\r\n";
private static final String boundary = "*****";
private String uploadFile(File sourceFile) {
HttpURLConnection.setFollowRedirects(false);
DataInputStream inStream = null;
try {
connection = (HttpURLConnection) new URL(URL_POST_MESSAGE_FILE).openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
String boundary = "---------------------------boundary";
String tail = lineEnd + "--" + boundary + "--" + lineEnd;
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
connection.setRequestProperty(modelHeader.getValue(), modelHeader.getValue());
String metadataPart = "--" + boundary + lineEnd
+ "Content-Disposition: form-data; name=\"metadata\"\r\n\r\n"
+ "" + lineEnd;
long fileLength = sourceFile.length() + tail.length();
String stringData = metadataPart + "--" + boundary + lineEnd
+ "Content-Disposition: form-data; name=\"fileToUpload\"; filename=\""
+ sourceFile.getName() + "\"\r\n"
+ "Content-Type: application/octet-stream" + lineEnd
+ "Content-Transfer-Encoding: binary" + lineEnd + "Content-length: " + fileLength + lineEnd + lineEnd;
long requestLength = stringData.length() + fileLength;
connection.setRequestProperty("Content-length", "" + requestLength);
connection.setFixedLengthStreamingMode((int) requestLength);
connection.connect();
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(stringData);
out.flush();
int bytesRead;
FileInputStream fileInputStream = new FileInputStream(sourceFile);
BufferedInputStream bufInput = new BufferedInputStream(fileInputStream);
byte buf[] = new byte[(int) sourceFile.length() / 200];
while ((bytesRead = bufInput.read(buf)) != -1) {
out.write(buf, 0, bytesRead);
out.flush();
}
out.writeBytes(tail);
out.flush();
out.close();
} catch (IOException e) {
Log.e(VolleyDownUpFiles.class.getSimpleName(), e.getMessage() + " ");
return null;
}
try {
inStream = new DataInputStream(connection.getInputStream());
String str;
if ((str = inStream.readLine()) != null) {
inStream.close();
return str;
}
} catch (IOException e) {
Log.e("Tag", e.getMessage());
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
return null;
}
或者更多更好的方法, 有一个库,我个人推荐给任何 android 喜欢 Light weight Volley for Api Integrations 的开发人员。
https://github.com/Lib-Jamun/Volley
dependencies {
compile 'tk.jamun:volley:0.0.4'
}
他的文档目前可用于0.0.4版本, 但是这个库的优点是 0.0.7 版本,你不需要手动解析或创建 JSON 你只需要传递你的模型 class 和其他自动完成的事情。 它的文件相关 classes 用于背景和正常使用,它对您的 Api 方法的响应非常强大,您可以获得更多东西。
我找到了一种使用 Volley 的方法。我能够使用从 here 获得的 InputStreamVollyRequest。通过将我的变量添加到参数并调用我的 php 文件,我能够成功地从我的数据库间接下载文件。下面是我现在成功执行的代码片段。 (关于我的文件路径和参数的细节已经被抽象出来)。请注意,参数似乎没有任何作用,但我抽象出了如何使用它们来确定相对文件路径。我也是如此 post 没有错误处理它只会将错误消息保存到应用程序上生成的文件中,文件名是 param1 的值。
Android: java
private InputStreamVolleyRequest generatePHPDownloadRequest(String param1Value, String param2Value)
{
Map<String,String> inParams = new HashMap<String,String>();
inParams.put("param1", param1Value);
inParams.put("param2", param2Value);
String requestURL = WebsiteInterface.DOWNLOAD_URL_STRING;
InputStreamVolleyRequest request = new InputStreamVolleyRequest(Request.Method.POST, requestURL,
new Response.Listener<byte[]>() {
@Override
public void onResponse(byte[] response) {
// TODO handle the response
try {
if (response!=null) {
FileOutputStream outputStream;
String name=param1Value;
outputStream = openFileOutput(name, Context.MODE_PRIVATE);
outputStream.write(response);
outputStream.close();
ReturnWithResult(RESULT_OK, getFilesDir().getAbsolutePath());
//Toast.makeText(this, "Download complete.", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
// TODO Auto-generated catch block
Log.d("KEY_ERROR", "UNABLE TO DOWNLOAD FILE");
e.printStackTrace();
ReturnWithResult(RESULT_CANCELED, "KEY_ERROR: UNABLE TO DOWNLOAD FILE");
}
}
} ,new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO handle the error
error.printStackTrace();
String msg = "unknown error";
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
//This indicates that the reuest has either time out or there is no connection
//Log.d(TAG, "Connection Error!");
msg = "Connection Error!";
} else if (error instanceof AuthFailureError) {
//Error indicating that there was an Authentication Failure while performing the request
//Log.d(TAG, "Authentication Error!");
msg = "Authentication Error!";
} else if (error instanceof ServerError) {
//Indicates that the server responded with a error response
//Log.d(TAG, "Server Error!");
msg = "Server Error!";
} else if (error instanceof NetworkError) {
//Indicates that there was network error while performing the request
//Log.d(TAG, "Network Error!");
msg = "Network Error!";
} else if (error instanceof ParseError) {
// Indicates that the server response could not be parsed
//Log.d(TAG, "Parsing Error!");
msg = "Parsing Error!";
}
VolleyLog.d(TAG, "Error: " + error.getMessage());
ReturnWithResult(Activity.RESULT_CANCELED, "VOLLEY: " + msg);
}
}, (HashMap<String, String>) inParams);
return request;
}
PHP
<?php
ini_set('display_errors',1);
if(!isset($_POST["param1"]))
{
exit("PARAM 1 EMPTY");
}
if(!isset($_POST["param2"]))
{
exit("PARAM 2 EMPTY");
}
$param1Value = $_POST["param1"];
$param2Value = $_POST["param2"];
$downloadPath = "<relative path from php file location to the desired file>";
readfile($downloadPath);
?>