class PostExportService {

    /**
     * Logger.
     */
    private static final Logger LOGGER = LogManager.getLogger(PostExportService.class);

    /**
     * User repository.
     */
    @Inject
    private UserRepository userRepository;

    /**
     * Article repository.
     */
    @Inject
    private ArticleRepository articleRepository;

    /**
     * Comment repository.
     */
    @Inject
    private CommentRepository commentRepository;

    /**
     * Pointtransfer management service.
     */
    @Inject
    private PointtransferMgmtService pointtransferMgmtService;

    /**
     * Exports all posts of a user's specified with the given user id.
     *
     * @param userId the given user id
     * @return download URL, returns {@code "-1"} if in sufficient balance, returns {@code null} if other exceptions
     */
    public String exportPosts(final String userId) {<FILL_FUNCTION_BODY>}
}

        final int pointDataExport = Symphonys.POINT_DATA_EXPORT;
        try {
            final JSONObject user = userRepository.get(userId);
            final int balance = user.optInt(UserExt.USER_POINT);

            if (balance - pointDataExport < 0) {
                return "-1";
            }
        } catch (final RepositoryException e) {
            LOGGER.log(Level.ERROR, "Checks user failed", e);

            return null;
        }

        final JSONArray posts = new JSONArray();

        Query query = new Query().setFilter(
                new PropertyFilter(Article.ARTICLE_AUTHOR_ID, FilterOperator.EQUAL, userId)).
                select(Keys.OBJECT_ID,
                        Article.ARTICLE_TITLE,
                        Article.ARTICLE_TAGS,
                        Article.ARTICLE_CONTENT,
                        Article.ARTICLE_CREATE_TIME);

        try {
            final List<JSONObject> articles = articleRepository.getList(query);
            for (final JSONObject article : articles) {
                final JSONObject post = new JSONObject();
                post.put("id", article.optString(Keys.OBJECT_ID));
                final JSONObject content = new JSONObject();
                content.put("title", article.optString(Article.ARTICLE_TITLE));
                content.put("tags", article.optString(Article.ARTICLE_TAGS));
                content.put("body", article.optString(Article.ARTICLE_CONTENT));
                post.put("content", content.toString());
                post.put("created", Article.ARTICLE_CREATE_TIME);
                post.put("type", "article");
                posts.put(post);
            }
        } catch (final Exception e) {
            LOGGER.log(Level.ERROR, "Export articles failed", e);
            return null;
        }

        query = new Query().setFilter(new PropertyFilter(Comment.COMMENT_AUTHOR_ID, FilterOperator.EQUAL, userId)).
                select(Keys.OBJECT_ID, Comment.COMMENT_CONTENT, Comment.COMMENT_CREATE_TIME);
        try {
            final List<JSONObject> comments = commentRepository.getList(query);
            for (final JSONObject comment : comments) {
                final JSONObject post = new JSONObject();
                post.put("id", comment.optString(Keys.OBJECT_ID));
                final JSONObject content = new JSONObject();
                content.put("title", "");
                content.put("tags", "");
                content.put("body", comment.optString(Comment.COMMENT_CONTENT));
                post.put("content", content.toString());
                post.put("created", Comment.COMMENT_CREATE_TIME);
                post.put("type", "comment");
                posts.put(post);
            }
        } catch (final Exception e) {
            LOGGER.log(Level.ERROR, "Export comments failed", e);
            return null;
        }

        LOGGER.info("Exporting posts [size=" + posts.length() + "]");

        final boolean succ = null != pointtransferMgmtService.transfer(userId, Pointtransfer.ID_C_SYS,
                Pointtransfer.TRANSFER_TYPE_C_DATA_EXPORT, Pointtransfer.TRANSFER_SUM_C_DATA_EXPORT,
                String.valueOf(posts.length()), System.currentTimeMillis(), "");
        if (!succ) {
            return null;
        }

        final String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String fileKey = "export-" + userId + "-" + uuid + ".zip";

        final String tmpDir = System.getProperty("java.io.tmpdir");
        String localFilePath = tmpDir + "/" + uuid + ".json";
        LOGGER.info(localFilePath);
        final File localFile = new File(localFilePath);

        try {
            final byte[] data = posts.toString(2).getBytes(StandardCharsets.UTF_8);

            try (final OutputStream output = new FileOutputStream(localFile)) {
                IOUtils.write(data, output);
            }

            final File zipFile = ZipUtil.zip(localFile);

            final FileInputStream inputStream = new FileInputStream(zipFile);
            final byte[] zipData = IOUtils.toByteArray(inputStream);

            if (Symphonys.QN_ENABLED) {
                final Auth auth = Auth.create(Symphonys.UPLOAD_QINIU_AK, Symphonys.UPLOAD_QINIU_SK);
                final UploadManager uploadManager = new UploadManager(new Configuration());
                uploadManager.put(zipData, fileKey, auth.uploadToken(Symphonys.UPLOAD_QINIU_BUCKET),
                        null, "application/zip", false);

                return Symphonys.UPLOAD_QINIU_DOMAIN + "/" + fileKey;
            } else {
                fileKey = FileUploadProcessor.genFilePath(fileKey);
                final String filePath = Symphonys.UPLOAD_LOCAL_DIR + fileKey;

                FileUtils.copyFile(zipFile, new File(filePath));

                return Latkes.getServePath() + "/upload/" + fileKey;
            }
        } catch (final Exception e) {
            LOGGER.log(Level.ERROR, "Uploading exprted data failed", e);

            return null;
        }
    
<no_super_class>