如何在Android上发布大型video服务器?

我试图发布一个大的video(近1 GB)。

我正在使用FTP将video发送到服务器,但上传会在一段时间后停止。 在服务器上的video崩溃,但我能够上传一个较小的video。

我还使用HTTP将video发送到服务器,作为Base64编码string发送,但编码时出现内存不足exception。

我试图上传video作为文件,但没有成功。 将大型video上传到服务器的最佳方法是什么?

Solutions Collecting From Web of "如何在Android上发布大型video服务器?"

使用HTTP POST,并将内容发布为基于表单的file upload (MIMEtypes:multipart / form-data)。 该系统是Web上用于发送表单和/或上传文件的标准。

使用HTTP分块发布模式,这样大小不需要事先知道,并且可以stream式传输任何小文件。 你仍然需要在服务器上做一些代码(例如在PHP中)来接受这个文件,并做一些必要的事情。

使用HttpURLConnection来启动连接。 然后使用我附加的类来发送数据。 它会创build正确的头文件等,然后将它用作OutputStream将原始数据写入它,然后调用close,然后完成。 你可以重写它的onHandleResult来处理结果的错误代码。

public class FormDataWriter extends FilterOutputStream{ private final HttpURLConnection con; /** * @param formName name of form in which data are sent * @param fileName * @param fileSize size of file, or -1 to use chunked encoding */ FormDataWriter(HttpURLConnection con, String formName, String fileName, long fileSize) throws IOException{ super(null); this.con = con; con.setDoOutput(true); String boundary = generateBoundary(); con.setRequestProperty(HTTP.CONTENT_TYPE, "multipart/form-data; charset=UTF-8; boundary="+boundary); { StringBuilder sb = new StringBuilder(); writePartHeader(boundary, formName, fileName==null ? null : "filename=\""+fileName+"\"", "application/octet-stream", sb); headerBytes = sb.toString().getBytes("UTF-8"); sb = new StringBuilder(); sb.append("\r\n"); sb.append("--"+boundary+"--\r\n"); footerBytes = sb.toString().getBytes(); } if(fileSize!=-1) { fileSize += headerBytes.length + footerBytes.length; con.setFixedLengthStreamingMode((int)fileSize); }else con.setChunkedStreamingMode(0x4000); out = con.getOutputStream(); } private byte[] headerBytes, footerBytes; private String generateBoundary() { StringBuilder sb = new StringBuilder(); Random rand = new Random(); int count = rand.nextInt(11) + 30; int N = 10+26+26; for(int i=0; i<count; i++) { int r = rand.nextInt(N); sb.append((char)(r<10 ? '0'+r : r<36 ? 'a'+r-10 : 'A'+r-36)); } return sb.toString(); } private void writePartHeader(String boundary, String name, String extraContentDispositions, String contentType, StringBuilder sb) { sb.append("--"+boundary+"\r\n"); sb.append("Content-Disposition: form-data; charset=UTF-8; name=\""+name+"\""); if(extraContentDispositions!=null) sb.append("; ").append(extraContentDispositions); sb.append("\r\n"); if(contentType!=null) sb.append("Content-Type: "+contentType+"\r\n"); sb.append("\r\n"); } @Override public void write(byte[] buffer, int offset, int length) throws IOException{ if(headerBytes!=null) { out.write(headerBytes); headerBytes = null; } out.write(buffer, offset, length); } @Override public void close() throws IOException{ flush(); if(footerBytes!=null) { out.write(footerBytes); footerBytes = null; } super.close(); int code = con.getResponseCode(); onHandleResult(code); } protected void onHandleResult(int code) throws IOException{ if(code!=200 && code!=201) throw new IOException("Upload error code: "+code); } } 

我猜这是因为大尺寸超时而失败的。

以来

小尺寸video上传成功

,我的build议是

  1. 将一个大文件分割成几个小文件。
  2. 根据networking状况一个一个或几个一起上传。
  3. 在服务器上join所有部分(全部成功上传)。
  4. 由于体积小,重新上传失败的部分将很容易。

只是一个理论。

这个网站可能有帮助。


新增08.01.2013

已经有一段时间了,不知道你是否还需要这个。 无论如何,我写了一些简单的代码实现上面的理论,主要是因为兴趣。

  1. 将一个大文件分割成几个小文件。 将大文件读入几个小部分。

     ByteBuffer bb = ByteBuffer.allocate(partSize); int bytesRead = fc.read(bb); if (bytesRead == -1) { break; } byte[] bytes = bb.array(); parts.put(new Part(createFileName(fileName, i), bytes)); 
  2. 根据networking状况一个一个或几个一起上传。

     Part part = parts.take(); if (part == Part.NULL) { parts.add(Part.NULL);// notify others to stop. break; } else { uploader.upload(part); } 
  3. 在服务器上join所有部分(全部成功上传)。 因为它是通过HTTP,所以它可以是任何语言,如Java,PHP,Python等。这里是一个java的例子。

     ... try (FileOutputStream dest = new FileOutputStream(destFile, true)) { FileChannel dc = dest.getChannel();// the final big file. for (long i = 0; i < count; i++) { File partFile = new File(destFileName + "." + i);// every small parts. if (!partFile.exists()) { break; } try (FileInputStream part = new FileInputStream(partFile)) { FileChannel pc = part.getChannel(); pc.transferTo(0, pc.size(), dc);// combine. } partFile.delete(); } statusCode = OK;// set ok at last. } catch (Exception e) { log.error("combine failed.", e); } 

我把所有的代码放在GitHub上 。 并做了一个Android的例子 。

请看看你是否仍然需要。

私人HttpsURLConnection conn = null;

conn.setDoInput(真);

conn.setDoOutput(真);

conn.setUseCaches(假);

conn.setChunkedStreamingMode(1024);