private int doAppendFile(String groupName, String appenderFileName, long fileSize, UploadCallback callback)
            throws FdfsException {
        if (Strings.isBlank(groupName) || Strings.isBlank(appenderFileName)) {
            return ERR_NO_EINVAL;
        }
        byte[] appenderFileNameByteArr =
                Strings.getBytes(appenderFileName, getFdfsClientConfig().getCharset());
        long bodyLength = 2 * FDFS_PROTO_PKG_LEN_SIZE + appenderFileNameByteArr.length + fileSize;
        byte[] header = Messages.createHeader(bodyLength, STORAGE_PROTO_CMD_APPEND_FILE);
        WriteByteArrayFragment request =
                new WriteByteArrayFragment((int) (header.length + bodyLength - fileSize));
        // fill header
        request.writeBytes(header);
        // fill appenderFileNameByteArr.length
        byte[] appenderFileNameByteArrLengthByteArr = new byte[8];
        Bytes.long2bytes(appenderFileNameByteArr.length, appenderFileNameByteArrLengthByteArr);
        request.writeBytes(appenderFileNameByteArrLengthByteArr);
        // fill fileSize
        byte[] fileSizeByteArr = new byte[8];
        Bytes.long2bytes(fileSize, fileSizeByteArr);
        request.writeBytes(fileSizeByteArr);
        // fill appenderFileNameByteArr
        request.writeBytes(appenderFileNameByteArr);
        // send
        Connection con = getUpdatableConnection(groupName, appenderFileName);
        InputStream is = null;
        OutputStream out = null;
        ResponseBody responseBody = null;
        int errorNo = 0;
        try {
            is = con.getInputStream();
            out = con.getOutputStream();
            out.write(request.getData());
            errorNo = callback.send(out);
            if (errorNo != 0) {
                return errorNo;
            }
            responseBody = Messages.readResponse(is, 0);
            if (responseBody.getErrorNo() != 0) {
                return responseBody.getErrorNo();
            }
            return 0;
        } catch (Exception e) {
            throw new FdfsException(e.getMessage(), e);
        } finally {
            con.close();
        }
    }