如何将视频文件作为 json 数据发送。 (不是文件名或路径,而是内容)到 Android
Posted
技术标签:
【中文标题】如何将视频文件作为 json 数据发送。 (不是文件名或路径,而是内容)到 Android【英文标题】:How to send video files as json data. (Not the file name or path but content) to Android 【发布时间】:2014-02-05 18:46:21 【问题描述】:我正在使用用 php 开发的 restful webservice。网络服务将发送数据图像。对于图像,它将发送图像名称,我们将准备好图像的 url 以进行下载。但是现在需要下载视频文件。我们可以像下载图片一样按照同样的方式(例如:image name = "myimage1.jpeg" url=www.xyz.com/images/myimage1.jpeg",我们会直接读取这个并在本地创建文件),但是想知道php有什么方法可以从php发送二进制字符串等数据,并在android端将其转换为电影文件。
(我们可以将图像作为 json 数据从 php webservice 发送。请给出一些代码)
注意:如何将来自 restful web 服务的图像/视频文件作为 json 数据发送
【问题讨论】:
理论上可行,但您需要传输的数据量会激增。这需要很长时间!但是,如果您仍然想尝试一下 - 请查看 Base64。 这是一个非常糟糕的主意,因为必须先完全传输数据,然后才能对其进行任何操作。您需要先下载视频,然后才能开始播放,而不是“流式传输”视频。 将视频数据嵌入到 JSON 中时,您假设有什么好处? 【参考方案1】:正如 ChriZzZ 所说,在 JSON 中这是不可取的(并且不是真正原生支持的)。
不过,您可以考虑使用BSON (Binary JSON)。特别是对于 PHP 实现,该站点提供了一个指向 Mongo 的链接,因此您可能需要检查一下。很遗憾,我没有可提供的代码。
【讨论】:
【参考方案2】:这里是根据 PHP 官方文档的信息。 希望它适用于视频文件。
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(serverURL);
MultipartEntity postEntity = new MultipartEntity();
File file = new File("file path to be put here");
postEntity.addPart("fileupload", new FileBody(file, "video/mp4"));
postEntity.addPart("loginKey", new StringBody(""+loginKey));
postEntity.addPart("message", new StringBody(message));
postEntity.addPart("token", new StringBody(token));
post.setEntity(postEntity);
response = client.execute(post);
【讨论】:
此代码用于将图像上传到服务器。我的要求是通过 PHP 网络服务发送图像/视频。实际上,您对上述内容有所了解。但是以 JSON 格式将数据作为 Web 服务发送的问题。(可以是任何东西)【参考方案3】:试试这个它对你有用。
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(URL);//
FileBody filebodyVideo = new FileBody(file);
StringBody title = new StringBody("Filename: " + filename);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("videoFile", filebodyVideo);
httppost.setEntity(reqEntity);
HttpResponse response = httpclient.execute( httppost );
【讨论】:
【参考方案4】:您为什么不在 Web 服务中接收视频的文件路径,而不是在 Web 服务中接收整个视频音频文件,因为在接收整个文件的情况下,可能会超出限制,您将收到来自 PHP 的无效 JSON 响应。因此,在服务器上检索视频的文件路径而不是响应视频本身更安全。
另一种方法是您使用 webview 并在 php 中放置下载链接,以防下载视频文件。
【讨论】:
【参考方案5】:这可能对你有帮助:
PHP 代码 (video.php)
<?php
if(isset($_GET['name']))
$video_name = $_GET['name'];
$path = "/path/to/videos/folder/$video_name"; //ex: video.mp4
$size=filesize($path);
$fm=@fopen($path,'rb');
if(!$fm)
// You can also redirect here
header ("HTTP/1.0 404 Not Found");
die();
$begin=0;
$end=$size;
if(isset($_SERVER['HTTP_RANGE']))
if(preg_match('/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER['HTTP_RANGE'], $matches))
$begin=intval($matches[0]);
if(!empty($matches[1]))
$end=intval($matches[1]);
if($begin>0||$end<$size)
header('HTTP/1.0 206 Partial Content');
else
header('HTTP/1.0 200 OK');
header("Content-Type: video/mp4");
header('Accept-Ranges: bytes');
header('Content-Length:'.($end-$begin));
header("Content-Disposition: inline;");
header("Content-Range: bytes $begin-$end/$size");
header("Content-Transfer-Encoding: binary\n");
header('Connection: close');
$cur=$begin;
fseek($fm,$begin,0);
while(!feof($fm)&&$cur<$end&&(connection_status()==0))
print fread($fm,min(1024*16,$end-$cur));
$cur+=1024*16;
usleep(1000);
die();
else
echo "Please provide a Video name (name=)";
?>
Java 代码(下载并保存视频到 SDCARD):
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
public class VideoSaveSDCARD extends Activity
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ProgressBack PB = new ProgressBack();
PB.execute("");
class ProgressBack extends AsyncTask<String,String,String>
ProgressDialog PD;
@Override
protected void onPreExecute()
PD= ProgressDialog.show(LoginPage.this,null, "Please Wait ...", true);
PD.setCancelable(true);
@Override
protected void doInBackground(String... arg0)
DownloadFile("http://yourserver/video.php?name=video.mp4","video.mp4");
protected void onPostExecute(Boolean result)
PD.dismiss();
public void DownloadFile(String fileURL, String fileName)
try
String RootDir = Environment.getExternalStorageDirectory()
+ File.separator + "Video";
File RootFile = new File(RootDir);
RootFile.mkdir();
// File root = Environment.getExternalStorageDirectory();
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
FileOutputStream f = new FileOutputStream(new File(RootFile,
fileName));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0)
f.write(buffer, 0, len1);
f.close();
catch (Exception e)
Log.d("Error....", e.toString());
【讨论】:
这是正常的做法。这就是我们正在做的事情。但我一直在寻找的是,有没有办法将图像/视频作为 json 数据本身的一部分发送(不仅仅是图像/视频的名称)。非常感谢。【参考方案6】:当然,您可以发送 JSON 格式的视频数据,但由于 JSON 本质上是一种带有多个保留字符的字符串格式,您必须对视频数据进行编码。 你可以使用任何你喜欢的方案——但是 BASE64 是一个被广泛接受的标准,所以我会使用它。
只需创建一个 JSON-String 对象并用 BASE-64 编码的视频数据填充它。
但要小心缓冲区溢出!!!因为许多 JSON 实现通常不会期望 JSON 中有巨大的数据元素,所以建议将数据流分成几个较小的块并一次交付一个......当然你也可以只流式传输 JSON 数据本身,但据我所知,大多数 JSON 堆栈都是串行操作的,因为您只能在完整的情况下解析有效的 JSON 字符串。
因此,性能方面最好的事情(如果您真的想将视频数据打包成 JSON,这显然不是 JSON 的初衷,并且应该为几乎所有设置提供更好的解决方案)应该是 BASE64 编码流中的视频,因此您可以将其块读取到内存中,将它们打包成 JSON 字符串并将它们发送到服务器,服务器可以使用这些块将视频流式传输到文件或播放它,或在内存中重建它。 ..
@BSON 之前提到过 - 建议使用它,因为 JSON 数据将被压缩。但这并没有改变您必须以不利的格式对视频数据进行编码的事实,这会使传输的数据膨胀,并且会在两端损失其公平份额的性能!
但我可以想象使用 JSON 进行视频传输的场景可能是可取的。如果您有大量的小视频(用户可以选择和整理的小视频或视频片段),那么一个易于处理的可靠数据结构来管理这些视频可能非常值得额外的传输成本......
【讨论】:
【参考方案7】:您可以将任何二进制文件编码为 base64,然后输出如下 JSON 字符串:
<?php
$fgc = file_get_contents('yourfile.gif'); //can be any binary
$bindata = base64_encode($fgc);
$arr = array('name'=>'yourfile.gif','mime'=>'image/gif','data'=>$bindata);
echo json_encode($arr);
?>
对于视频,请使用您喜欢的 mime 类型...
在 Android 端,解码数据并使用 mime 类型,因此选择正确的视图等...
【讨论】:
【参考方案8】:从 PHP 发送 JSON 格式的二进制数据非常简单:
$data = file_get_contents($filename);
echo json_encode(array('filecontent' => $data));
至少在理论上这是可行的。它在实践中不起作用的原因是$data
的大小有限(必须符合内存限制),并且 JSON 并不是要传输兆字节的数据。
编码效率低下。要么您使用本机字节,然后您将体验到任何不可打印字符的转义序列,使这些字节变大六倍(Unicode 转义序列使用反斜杠、字母“u”和四个十六进制数字)。或者您使用 base64 编码,这将使每个字节都增加大约 33%。不计算最基本的 JSON 包装的开销。
提供带有适当标头的本机字节流似乎是更好的主意。您可以直接将该流输入视频编解码器进行回放,而无需解析 JSON、解码 base64 并将所有内容重新组合成视频数据流。
【讨论】:
【参考方案9】:import java.io.File;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
@Path("/file")
public class DownloadVideoREST
private static final String VIDEO_FILE = "E:\\xyz.flv";
@GET
@Path("/video")
@Produces("video/flv")
public Response getVideoFile()
File file = new File(VIDEO_FILE);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=\"abc.flv\"");
return response.build();
@GET
@Path("/fileName/video")
@Produces("video/flv")
public Response getFileInVideoFormat(@PathParam("fileName") String fileName)
System.out.println("File requested is : " + fileName);
if(fileName == null || fileName.isEmpty())
ResponseBuilder response = Response.status(Status.BAD_REQUEST);
return response.build();
File file = new File("c:/abc.flv");
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=abc.flv");
return response.build();
【讨论】:
这根本不是问题的答案。这是 Java 将视频文件作为二进制流附件发送。没有 PHP,没有 JSON以上是关于如何将视频文件作为 json 数据发送。 (不是文件名或路径,而是内容)到 Android的主要内容,如果未能解决你的问题,请参考以下文章