如何使用Java上传大块文件?

时间:2011-05-20 15:55:44

标签: java file file-upload

我需要使用Java上传大块文件。

我可以参考哪些示例代码?

6 个答案:

答案 0 :(得分:3)

*可以使用plupload完成。 这是样本。 我的index.html如下: -

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Upload</title>
    <!-- production -->
    <script type="text/javascript" src="js/plupload.full.min.js"></script>
    <!-- debug 
    <script type="text/javascript" src="../js/moxie.js"></script>
    <script type="text/javascript" src="../js/plupload.dev.js"></script>
    -->
    </head>
    <body style="font: 13px Verdana; background: #eee; color: #333">
    <div id="filelist"></div>
    <br />
        <button id="pickfiles" >Select file</button> 
        <button id="uploadfiles" >Upload</button>
        <div id="container">
    </div>
    <br />
    <pre id="console"></pre>
    <script type="text/javascript">
    // Custom example logic
    var uploader = new plupload.Uploader({
        runtimes : 'html5',
        browse_button : 'pickfiles', // you can pass an id...
        container: document.getElementById('container'), // ... or DOM Element itself
        url : 'UploadAction',//upload.php
        chunk_size : '1mb',
        method:'POST',
        flash_swf_url : 'js/Moxie.swf',
        silverlight_xap_url : 'js/Moxie.xap',

        filters : {
            max_file_size : '100gb',
            mime_types: [
                {title : "Image files", extensions : "jpg,gif,png"},
                {title : "Zip files", extensions : "zip,txt,vmdk"}
            ]
        },
        init: {
            PostInit: function() {
                document.getElementById('filelist').innerHTML = '';
                document.getElementById('uploadfiles').onclick = function() {
                    uploader.start();
                    return false;
                };
            },
            FilesAdded: function(up, files) {
                plupload.each(files, function(file) {
                    document.getElementById('filelist').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></div>';
                });
            },
            UploadProgress: function(up, file) {
                document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
            },
            Error: function(up, err) {
                document.getElementById('console').appendChild(document.createTextNode("\nError #" + err.code + ": " + err.message));
            }
        }
    });
    uploader.init();
    </script>
    </body>
    </html>
<!-- end snippet -->

我的java后端代码(Servlet)如下: -

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
public class UploadAction extends HttpServlet {
    private static final long serialVersionUID = 3447685998419256747L;
    private static final String RESP_SUCCESS = "{\"jsonrpc\" : \"2.0\", \"result\" : \"success\", \"id\" : \"id\"}";
    private static final String RESP_ERROR = "{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 101, \"message\": \"Failed to open input stream.\"}, \"id\" : \"id\"}";
    public static final String JSON = "application/json";
    public static final int BUF_SIZE = 2 * 1024;
    public static final String FileDir = "/home/asjha/uploads/";

    private int chunk;
    private int chunks;
    private String name;
    private String user;
    private String time;
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String responseString = RESP_SUCCESS;
        boolean isMultipart = ServletFileUpload.isMultipartContent(req);

        if(isMultipart){
            ServletFileUpload upload = new ServletFileUpload();
            try {
                FileItemIterator iter = upload.getItemIterator(req);
                while (iter.hasNext()) {
                    FileItemStream item = iter.next();
                    InputStream input = item.openStream();
                    // Handle a form field.
                    if(item.isFormField()){
                        String fileName = item.getFieldName();
                        String value = Streams.asString(input);
                        if("name".equals(fileName)){
                            this.name = value;
                        }else if("chunks".equals(fileName)){
                            this.chunks = Integer.parseInt(value);
                        }else if("chunk".equals(fileName)){
                            this.chunk = Integer.parseInt(value);
                        }else if("user".equals(fileName)){
                            this.user = value;
                        }else if("time".equals(fileName)){
                            this.time = value;
                        }
                    }

                    // Handle a multi-part MIME encoded file.
                    else {
                        File dstFile = new File(FileDir);
                        if (!dstFile.exists()){
                            dstFile.mkdirs();
                        }

                        File dst = new File(dstFile.getPath()+ "/" + this.name);

                        saveUploadFile(input, dst);
                    }
                }
            }
            catch (Exception e) {
                responseString = RESP_ERROR;
                e.printStackTrace();
            }
        }

        // Not a multi-part MIME request.
        else {
            responseString = RESP_ERROR;
        }

        if(this.chunk == this.chunks - 1){
            System.out.println("name"+this.name);
        }
        resp.setContentType(JSON);
        byte[] responseBytes = responseString.getBytes();
        resp.setContentLength(responseBytes.length);
        ServletOutputStream output = resp.getOutputStream();
        output.write(responseBytes);
        output.flush();
    }
    private void saveUploadFile(InputStream input, File dst) throws IOException {
        OutputStream out = null;
        try {
            if (dst.exists()) {
                out = new BufferedOutputStream(new FileOutputStream(dst, true),
                        BUF_SIZE);
            } else {
                out = new BufferedOutputStream(new FileOutputStream(dst),
                        BUF_SIZE);
            }
            byte[] buffer = new byte[BUF_SIZE];
            int len = 0;
            while ((len = input.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != input) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

请参阅plupload了解详细信息,在github上,您可以看到jakobadam和岩石的示例项目。

如果需要上传多个文件,请告诉我。使用plupload我们可以上传任意数量的任何大小的文件。此示例适用于非常大的单个文件上载。 别忘了包含plupload.full.min.js。希望这有助于*强调文字**

答案 1 :(得分:0)

使用RandomAccessFile。我已经相信这已经被覆盖了。

java file input with rewind()/reset() capability

基本上你只是寻找起点,从那里写出你想要的许多字节,并记住你停止写作的那一点。

答案 2 :(得分:0)

您可以自行分解文件,使用Socket API发送文件,然后重新组合文件。

答案 3 :(得分:0)

试试Apache Commons upload。它支持流媒体,可能适合您。

答案 4 :(得分:0)

如果您使用的是Java,请使用Arivus Nioserver gradle依赖 - &gt;编译&#39; org.arivu:nioserver:1.0.3&#39;。没有文件大小限制。

答案 5 :(得分:0)

以下是使用块上传文件的本机Java代码示例:

final String       LF = "\r\n"; // Line separator required by multipart/form-data. Can be static class constant
final String boundary = Long.toHexString(System.currentTimeMillis()); // Just generate some unique random value.

HttpURLConnection connection = (HttpURLConnection) new URL("http://some.com/upload").openConnection();
try {
    connection.setDoOutput(true);
    connection.setChunkedStreamingMode(4096);
    connection.setRequestMethod("POST");
    connection.addRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    connection.addRequestProperty("Accept", "application/json");
    connection.addRequestProperty("Authorization", myToken);
    try (OutputStream os = connection.getOutputStream();
            Writer writer = new OutputStreamWriter(os, StandardCharsets.UTF_8)) {
        writer.append("--").append(boundary).append(LF);
        writer.append("Content-Disposition: form-data; name=\"dataFile\"; filename=\"file.zip\"").append(LF);
        writer.append("Content-Type: application/zip").append(LF);
        writer.append(LF);
        writer.flush();

        // Write body
        writeBinaryBody(os);
        writer.append(LF).append("--").append(boundary).append("--").append(LF);
        writer.flush();
        os.flush();
    }
    if (200 != connection.getResponseCode()) {
        try (Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)) {
            // Handle error here
        }
    }
} finally {
    connection.disconnect();
}

本示例中的代码基于this answer,有关从Java上传http文件。区别在于对connection.setChunkedStreamingMode(4096);的调用定义了应使用分块的流。